C++---》stl : pair 从使用到模拟实现

一. pair简述

pair类,一组值,它呢将两个值(values)耦合(couples)到一块,这两个值的类型可能是不一样的比如T1,T2,, 这两个各自的值可以通过,pair的public的成员变量:first和second来访问。

二 . 拷贝构造和makepair

简单来说pair是一个模板类 可以理解为 :

复制代码
template<class first_type,class second_type> 
pair{

// 构造函数
// 其他成员函数 

public:
   first_type first;
   first_type second;

}

2.1 默认空参构造

如下代码:

cpp 复制代码
std::pair <std::string, double> product1;       // default constructor
cout << product1.first << " : " << product1.second;

本质上他会根据你的pair中的两个成员变量: first 和second:这个类具体化的string类和double类,调用他们的空参构造来初始化你的first和second得到的结果就是: 一个空串和一个0

2.2 值初始化构造

如下代码:

cpp 复制代码
const string str = "watermelon";
pair<string, int>my_value_init_pair(str,100);

cout << my_value_init_pair.first << " : " << my_value_init_pair.second << endl;

std::pair <std::string, double> product2("tomatoes", 2.30);   
cout << product2.first << " : " << product2.second << endl;

输出结果:

显然我们的pair我们传递的是一个const str和一个整数:100,调用的构造函数:

initialization (3) pair (const first_type& a, const second_type& b);

这个时候实例化也就是pari(const string& a, const int& b). 我们的传递的是第一组: 是一个 const string 和一个100 ,分别去对应a和b。 值得注意的是第二组传递的是 一个字符串"tomatoes" 它传递给 const string&a的时候呢 会进行一个构造 传递给string的的构造 构造出一个string对象。

2.3 最值得一谈的拷贝构造

copy (2) template<class U, class V> pair (const pair<U,V>& pr)

参考如下代码:

cpp 复制代码
pair<const char*, int> other_type_pair("hello world",10000);// 不同类型

std::pair <string, double> identical_type_pair("tomatoes", 2.30);   // 相同类型

std::pair <string, double> product3(other_type_pair);          // 用不同类型的pair类的实例化
std::pair <string, double> product4(identical_type_pair);          // copy constructor 

cout << product3.first << " : " << product3.second << endl;
cout << product4.first << " : " << product4.second << endl;

输出结果:

拓展:

我们的第一张图片的是不可以修改,而经过拷贝构造后却可以修改,这说明一个事情,当进行不同类型的拷贝构造实实在在的是把值赋给了我们的pair,而不是限定类型,这是如何做到的呢?

参考如下定义: 这个巧妙的拷贝构造 :

template<class U, class V> pair (const pair<U,V>& pr)

看代码中的例子: 第一个pair是pair<const char*,int> 类型的 而我们的product3是属于pair <string, double> 类型的 二者显然不是一个类型的,但是我们pair的拷贝构造say: i dont care! 当实例化的时候 U和V会自动实例化传进来的pair 我们需要做的仅仅只是一个事情就是把你这个家伙的值赋给当前pair<string,double>类的对象的成员即可:

大概实现如下代码:(这里的有一个小小的bug 在最后模拟实现解决咯!)

cpp 复制代码
namespace mystl {
	template<class first_type, class second_type>
	class pair {

		// 构造函数
		template<class U, class V> pair(const pair<U, V>& pr) {

			first = pr.first;
			second = pr.second;

		}




		// 其他成员函数 

	public:
		first_type first;
		first_type second;

	};
}

三 . pair类的赋值操作符重载和常用的makepair函数

3.1 赋值重载

继续用这个例子,发现不然类型的pair依然可以进行一个赋值重载,amazing一下下,这也说明本质上我们的赋值重载也是跟pair的拷贝构造一样 :模板化的。

这里的赋值重载的实现: 可以用一下现代写法:借组swap 和拷贝构造

cpp 复制代码
template<class U, class V>
		pair<first_type, second_type> operator=( pair<U, V> temp) {

std::swap(temp.first,this->first);
std::swap(temp.second,this->second);
return *this;
}

3.2 makepair的使用以及理解它的存在

头文件是 : #include<utility>

谈几个很简单的使用场景: 我们写了一个pair: pair<string,double> pr1;

但是我们仅仅是先定义在这还没打算给他值,我们会调用赋值重载。 pr1 = pr2;

比如我们的pr2 : pair<const char*,int> pr2 又或者 pair<string ,double> pr2

又或者是pair<const string,int> pr2("dasdas",12312); 不管你的pr2是哪种类型的,我们的赋值重载都可以帮你兜底,因为他是模板化的: 来者不拒,只要你能给我的成员变量赋值即可: 为什么呢? 我们的pr1的成员变量类型:string : 它可以接受 const string 又或者 const char* 的字符串

ok,再次捋清楚了一遍pair的模板化赋值重载,那么我们为什么要有make_pair呢? 简单来说每次我们想整一个pair类 然后写上值: 比如上面我们本来仅仅是想让pr2的内容赋值给pr1但是每次我都要乖乖的写好类型的前缀: pair<const string,int> 又或者..... 这该死的类型还不如自动去推导,所以我们的make_pair说我模板化了,我来帮你推导类型,返回值根据你给定的来推导吧。

demo代码:

cpp 复制代码
int main() {
	std::pair <std::string, int> planet, homeplanet;
	pair <const char* const, int> pr("sadasdsad", 123123);

	homeplanet = pr;

	planet = std::make_pair("Earth", 6371);

	homeplanet = planet;

	std::cout << "Home planet: " << homeplanet.first << '\n';
	std::cout << "Planet size: " << homeplanet.second << '\n';
	return 0;
}

输出:

四. 模拟实现pair类

如下代码 : 具体实现讲解如上文已经阐述足够清楚:

cpp 复制代码
namespace mystl {

	
	template<class first_type, class second_type>
	class pair {
	public:
		// 构造函数
		// 空参构造
		pair() {
		}
		// 值构造
		pair(const first_type& a, const second_type& b)
			: first(a),second(b)
		{
		}
		// 拷贝构造
		/*template<class U, class V> pair(const pair<U, V>& pr) {

			first = pr.first;
			second = pr.second;
		}*/
		template<class U, class V> pair(const pair<U, V>& pr)
		:first(pr.first),
		second(pr.second) {
		}
		// 赋值重载
		template<class U, class V>
		pair<first_type, second_type>& operator=( const pair<U, V> & pr) {

			first = pr.first;
			second = pr.second;
			return *this;
	  }

		// 其他成员函数 

	public:
		first_type first;
		second_type second;

	};

	template <class T1, class T2>
	pair<T1, T2> make_pair(T1 x, T2 y) {
		return pair<T1, T2>(x, y);
	}

}

值得注意我在模拟实现它的时候遇到的第一个问题是: 关于模板类函数 make_pair的定义应该放在pair类的后面 不然会导致pair类未声明的错误。

第二个错误比较有意思 :

error C2789: "mystl::pair<const char *const ,int>::first": 必须初始化常量限定类型的对象

也就是对于拷贝构造这个地方,

mystl::pair <const char*const , int> pr("sadasdsad", 123123); 像这样的测试用例

对于const char*const 是第一个成员变量的类型,这样是常量类型所以要求要初始化的时候给值。

相关推荐
林中青木3 小时前
读写INI文件源码(点击关注)
c++·ini文件读取
running thunderbolt3 小时前
项目---网络通信组件JsonRpc
linux·服务器·c语言·开发语言·网络·c++·性能优化
app出海创收老李3 小时前
海外独立创收日记(5)-上个月收入回顾与本月计划
前端·后端·程序员
每天进步一点_JL3 小时前
Docker 是什么?
后端·docker·容器
app出海创收老李3 小时前
海外独立创收日记(4)-第一笔汇款
前端·后端·程序员
咕白m6254 小时前
Python 将 Excel 转换为图片:实现数据可视化
后端·python
青岛少儿编程-王老师4 小时前
CCF编程能力等级认证GESP—C++6级—20250927
java·c++·算法
ajassi20004 小时前
开源 C++ QT QML 开发(十)通讯--串口
c++·qt·开源
Janspran4 小时前
监控系统2 - framebuffer
c++