pair
c++11后pair可以理解为tuple的子集(接受2个类型),可以使用tuple-like接口
std::get<0>(pr); // pr.first
std::get<1>(pr); // pr.second
std::tuple_size<PairType>::value; // return 2
std::tuple_element<0, PairType>::type; // pr.first's type
std::pair<int, float> pa = std::make_pair(100, 3.14); // make_pair自动检测参数类型,可以不传模板实参
std::tie(std::ignore, val) = pa; // extract 3.14
tuple
tuple是特殊的容器,不允许迭代
tuple可以是引用,get方法不能传变量(因为是在编译阶段确定get第几个元素的)
std::string str;
double dou;
std::tuple<string&, double&> tp(str, dou); // 支持引用
std::get<0>(tp) = "hello world"; // str now is "hello world"
int i = 0;
std::get<i>(tp); // error,不能传递变量
便捷函数make_tuple()和tie()
auto tp = std::make_tuple(22, 3.14, "hello"); // 自动推导
string s;
auto tp1 = std::make_tuple(std::ref(s)); // 相当于tuple<string&> tp1 = ...,改变tp也能改变s
int i;
float j;
std::string k;
std::make_tuple<std::ref(i), std::ref(j), std::ref(k)> = tp; // 写法1,总感觉很奇怪的写法,改变i能改变tp里的int(22)
std::tie(i, j, k) = tp; // 写法2,此写法更方便,好理解
std::tie(i, std::ignore, k) = tp; // 忽略tp中的float(3.14)
tuple构造函数被定义为explicit,所以不支持隐式转换
std::tuple<int, string> tp = {100, "hello"}; // error, 应该写成 ... = std::make_tuple(100, "hello");
// 拿tuple当返回值,或在容器内初始化都不行,因为都涉及隐式转换
std::vector<std::tuple<int, string>> vec{ {100, "hello"}, {200, "world" }; // error
std::tuple<int, float> foo() { return {100, "hello"}; } // error
其他tuple特性
std::tuple_element<3, decltype(tp)>::type elem; // 声明elem使用tp第三个元素的类型
std::tuple_size<decltype(tp)>::value; // 返回tp有几个元素
// tuple合并,也支持pair
int n;
std::tuple_cat(tp, std::make_pair(2, "foo"), std::tie(n)); // 将tp, pair, 一个std::tuple<int&>类型合并到一起
shared_ptr
shared_ptr<int> sp = new int; // error, 因为接受普通指针的构造函数是explicit的
传入可调用对象控制sp析构
shared_ptr<int> sp(new int, [callable object]); // 比如lambda
shared_ptr小坑
对于动态数组,shared_ptr的模板实参不能使数组,unique_ptr可以(实际遇到再细品)
std::shared_ptr<int[]> sp(new int[10]); // error
std::unique_ptr<int[]> up(new int[10]); // right
weak_ptr
很微妙,简而言之是解决sp在相互引用时某对象无法析构的问题,见standard std P86的例子
wp.expired(); // 看wp指向的sp是否还有引用,等同于wp.use_count(),但速度较快(c++标准库明确说了use_count()效率不行)
std::enable_shared_from_this<T> 这是个基类
想在类内拿到当前类的shared_ptr版本(正常只能获取到this,一个普通指针),继承此基类,并使用shared_from_this()获取
class Test : public std::enable_shared_from_this<Test>
{
void foo() { mem->push(std::shared_from_this()); } // 拿到this的sp版本
}
拿sp版本的目的是有一个场景:两个sp指向同一个this会导致double free
!别在类的构造函数中使用,原因详见P91