一、Pairs
1. 定义
Pairs为一个结构体,这样它的所有成员都是public的。可以更加方便的进行访问。
namespace std {
template <typename T1, typename T2>
struct pair {
//member
T1 first;
T2 second;
}
}
2. 操作
Operation | Effect |
---|---|
pair<T1, T2> | 创建一个pair并使用类型T1和T2的默认构造器来初始化元素 |
pair<T1, T2> p(val1, val2) | 创建一个pair并使用val1和val2来初始化元素 |
pair<T1, T2> p(piecewise_construct, t1, t2) | 创建一个pair并使用tuples的t1和t2来初始化元素 |
pair<T1, T2> p(p2) | Copy 构造器 |
pair<T1, T2> p(rv1, rv2) | 创建一个pair并使用rv1和rv2来move初始化元素 |
pair<T1, T2> p(rv) | Move 构造器 |
p = p2 | 将p2赋值给p |
p = rv | 将rv移动赋值给p |
p.first p.second | 访问p的第一和第二个元素 |
get<0>(p) get<1>(p) | 和p.first p.second 相同 (C++11提出的) |
p1 == p2 | 当p1和p2的first和second都相等的时候p1和p2相等 |
p1 != p2 | 当p1和p2的first和second有一个不相等的时候,p1和p2不相等 |
p1 < p2 | 当p1的first小于p2的first,或者当first相等p1的second小于p2的second的时候p1 < p2。 |
p1 <= p2 | 当p1的first小于等于p2的first,或者当first相等p1的second小于等于p2的second的时候p1 < p2 |
p1.swap(p2) | 交换p1和p2的值(c++11) |
swap(p1, p2) | 使用全局swap函数交换p1和p2的值(c++11) |
make_pair(val1, val2) | 返回一个使用val1和val2的类型和值构建的pair |
其中c++11为Pairs添加了一些额外的内容。
1. 支持move构造和赋值
2. 支持隐式类型转换构造和赋值
3. 支持tuple的构造
3. make_pair函数定义
make_pair
是使用最多的一个函数,通过该函数我们可以直接返回一个pairs
。
- 如下为c++11之前的
make_pair
函数定义。
namespace std {
template <template T1, template T2>
pair<T1, T2> make_pair(const T1& x, const T2& y) {
return pair<T1, T2>(x, y);
}
}
并且由于该函数使用了函数模板,所在不需要指定参数类型。
因此对于 std::pair<int, char>(4, 'a')
可以写成 std::make_pair(4, 'a')
。
- c++11的make_pair函数定义则引入了move的概念,其定义如下
namespace std {
template <template T1, template T2>
pair<T1, T2> make_pair(const T1&& x, const T2&& y) {
return pair<T1, T2>(x, y);
}
}
- 这里我们可以通过使用std::move()来强制使用move语义
std::string s, t;
...
auto p = std::make_pair(std::move(s), std::move(t));
...
- std::ref()来强制使用ref语义
std::int i, j;
...
auto p = std::make_pair(std::ref(i), std::ref(j));
++p.first;
++i;
std::cout << "i = " << i << std::endl; // i = 2
...
4. Pair的比较
- 判断两个pair是否相等的定义如下:
namespace std {
template <typename T1, typename T2>
bool operator== (const pair<T1, T2>& x, const pair<T1, T2>& y) {
return x.first == y.first && x.second == y.second;
}
}
从定义中我们可以看到只有当pair的first和second都相等的时候,两个pair才会相等。
- 判断两个pair的大小的定义如下:
namesapce std {
template <typename T1, typename T2>
bool operator< (const pair<T1, T2>& x, const pair<T1, T2>& y) {
return x.first < y.first || (!(y.first < x.first) && x.second < y.second);
}
}
从定义中我们可以看到在比较大小的时候first元素具有高优先级,即如果first可以比较出大小则结束,否则继续比较second元素的大小。
二、Tuples
相对于 pairs
来说,tuples
可以有多个元素。
1. 定义
namespace std {
template <typename... Types> //c++11 表示多个参数模板
class tuple {
public:
explicit tuple(const Types&...); //显示构造函数
template <typename... UTypes> explicit tuple(UTypes&&...); //显示构造函数, move语义, 隐式的类型转换
...
}
}
从定义我们可以看出,tuple可以接受任意多个参数,支持move语义和隐式类型转换。并且需要被显示的构造。
2. 操作
Operation | Effect |
---|---|
tuple<T1, T2, ..., Tn> | 创建一个tuple并使用类型T1-Tn的默认构造器来分别初始化元素 |
tuple<T1, T2, ..., Tn> p(val1, val2, ..., valn) | 创建一个tuple并使用val1, val2, …, valn来分别初始化对应的元素 |
tuple<T1, T2> t(p) | 对于只有两个元素的tuple可以使用一个pair来进行构造 |
t = t2 | 将t2赋值给t |
t1 == t2 | 当t1和t2的所有元素都相等的时候t1和t2相等 |
t1 != t2 | 当t1和t2的元素有一个不相等的时候,t1和t2不相等 |
t1 < t2 | 从第一个元素开始比较,只要当前元素可以判断出是否小于就返回 |
t1 <= t2 | 从第一个元素开始比较,只要当前元素可以判断出是否小于等于就返回 |
t1.swap(t2) | 交换t1和t2的值(c++11) |
swap(t1, t2) | 使用全局swap函数交换t1和t2的值(c++11) |
make_tuple(v1, v2, ..., ) | 返回一个使用v1,v2,…的类型和值d的一个tuple |
tie(ref1, ref2,...) | 返回一个使用v1, v2,…的类型以及使用引用赋值的一个tuple |
- *
make_tuple
函数。make_tuple是使用比较频繁的一个函数。如下为该函数的使用举例:
string s;
make_tuple(s); //默认构造
make_tuple(ref(s)) //使用引用构造
make_tuple(move(s)) //使用move语义进行构造
- *
get<index>(tuple)
该函数是得到tuple的第index个元素。如下为该函数的使用举例:
tuple<int, float, string> t(77, 1.1, "hello world");
auto x = get<0>(t) // 取值, x = 77
get<0>(t) = 11 // 赋值, t的第0个元素的值变为11
- *
tie(ref1,ref2,...)
该函数是为tuple的每一个元素建立一个外部引用。举例如下。
tuple<int, float, string> t(77, 1.1, "hello world");
int i;
float f;
string s;
tie(i, f, s) = t; //将t中的每一个元素和外部的一个变量进行绑定
这里我们可以使用ignore关键字来对tie中的某一个元素进行缺省。如下。
tuple<int, float, string> t(77, 1.1, "hello world");
int i;
string s;
tie(i, ignore, s) = t; //将t中的每一个元素和外部的一个变量进行绑定
- *额外的几个函数:
tuple_size<tupletype>::value
得到该tuple的元素个数tuple_element<idx, typletype>::type
得到该tuple的第idx的元素类型tuple_cat()
将多个tuple合成为一个tuple
typedef tuple<int, float, string> TupleType;
tuple_size<TupleType>::value // 3
tupel_element<1, TupleType>::type // float
int n;
auto tt = tuple_cat(make_tuple(4,1.1,"hello"), tie(n)); //