一. 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 在最后模拟实现解决咯!)
cppnamespace 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 是第一个成员变量的类型,这样是常量类型所以要求要初始化的时候给值。