构造函数
std::pair有三种构造函数形式
pair(const T1& x,const T2& y);
pair(U&& x, V&& y);
template <typename... Args1, typename... Args2>
pair(piecewise_construct_t,
tuple<Args1...> first_args,
tuple<Args2...> second_args);
前两个构造函数是我们常见的形式,传递一个实参给first,另一个实参给second:
std::pair<char*, int> a("age",42);
C++ standard指明,构造函数可能的话将使用支持move语义,否则使用copy语义。
第三个构造函数的含义是,将first_args tuple中的元素作为参数传递给first类型的构造函数,first_args tuple中的元素作为参数传递给second类型的构造函数,piecewise_construct_t是一个struct类型。
举例:
tuple<int, float> t(1,2.22);
pair<int,Foo> p(std::piecewise_construct, std::make_tuple<42>, t);
std::piecewise_construct是std内部声明的一个变量,t中的1和2.22将作为Foo类的构造函数参数传入。由于pair的第三种构造函数必须有两个tuple,所以42也需要使用tuple包起来。
这种初始化形式的必要性发生在当我们需要emplace一个新的元素到map或multimap中时
std::make_pair
当传递std::pair类型的函数参数,我们使用std::make_pair更为方便,并且无需写出模板参数
func(std::make_pair("age", 42));
这样做的代价是,类型推断可能并不准确,如"age"推断为const char*而非const char[2],对类型要求精确的场景下应注意。
比较
当两个元素都相同时,两个pair才视为相等;first优先级大于second,当first不等时,返回first比较结果,否则继续比较second
移动语义和引用语义
移动:
std::string s1, s2;
auto p = std::make_pair(std::move(s1), std::move(s2));
// 移动s1, s2到pair中,之后不再使用
引用:
int i = 0;
auto p = std::make_pair(std::ref(i), std::ref(i)); // auto推导类型为std::pair<int&, int&>
// 或者
// auto p = std::pair<int&, int&>(i, i);
p.first++;
p.second++;
// 此时i = 2