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

一. pair简述

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

二 . 拷贝构造和makepair 

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

template
pair{
// 构造函数
// 其他成员函数
public:
   first_type first;
   first_type second;
}

2.1 默认空参构造

   如下代码:

std::pair  product1;       // default constructor
cout << product1.first << " : " << product1.second;

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

2.2 值初始化构造

 如下代码:

const string str = "watermelon";
pairmy_value_init_pair(str,100);
cout << my_value_init_pair.first << " : " << my_value_init_pair.second << endl;
std::pair  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 pair (const pair& pr)

参考如下代码:

pair other_type_pair("hello world",10000);// 不同类型
std::pair  identical_type_pair("tomatoes", 2.30);   // 相同类型
std::pair  product3(other_type_pair);          // 用不同类型的pair类的实例化
std::pair  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 在最后模拟实现解决咯!)

namespace mystl {
	template
	class pair {
		// 构造函数
		template pair(const pair& pr) {
			first = pr.first;
			second = pr.second;
		}
		// 其他成员函数
	public:
		first_type first;
		first_type second;
	};
}

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

 3.1 赋值重载

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

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

template
		pair operator=( pair 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代码:

int main() {
	std::pair  planet, homeplanet;
	pair  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类

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

namespace mystl {
	template
	class pair {
	public:
		// 构造函数
		// 空参构造
		pair() {
		}
		// 值构造
		pair(const first_type& a, const second_type& b)
			: first(a),second(b)
		{
		}
		// 拷贝构造
		/*template pair(const pair& pr) {
			first = pr.first;
			second = pr.second;
		}*/
		template pair(const pair& pr)
		:first(pr.first),
		second(pr.second) {
		}
		// 赋值重载
		template
		pair& operator=( const pair & pr) {
			first = pr.first;
			second = pr.second;
			return *this;
	  }
		// 其他成员函数
	public:
		first_type first;
		second_type second;
	};
	template 
	pair make_pair(T1 x, T2 y) {
		return pair(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 是第一个成员变量的类型,这样是常量类型所以要求要初始化的时候给值。

posted @ 2025-11-09 06:55  ycfenxi  阅读(7)  评论(0)    收藏  举报