1. 动态内存与智能指针
share_ptr允许多个指针指向同一个对象;unique_ptr则“独占”所指向的对象;weak_ptr为伴随类,指向share_ptr所管理的对象。
share_ptr类
share_ptr也是一类模板,通过指明类型的方式进行使用,如下所示:
shared_ptr<string> pl; // shared_ptr,可以指向string shared_ptr<list<int>> p2; //shared_ptr,可以指向int的list
默认初始化的智能指针中保存着一个空指针。智能指针的使用方式与普通指针类似。解引用一个智能指针返回它指向的对象。如果在一个条件判断中使用智能指针,效果就是检测它是否为空:
// 如果p1不为空,检查它是否指向一个空string if (pl && p1->empty()) *p1 = "hi"; // 如果p1指向一个空string,解引用p1,将一个新值赋予string
下表为share_ptr以及unique_ptr对应的操作:
make_shared函数
最安全的分配和使用动态内存的方式是调用make_shared标准库函数。
此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。与智能指针一样,make_shared也定义在头文件memory 中。当要用make_shared时,必须指定想要创建的对象的类型。定义方式与模板类相同,在函数名之后跟一个尖括号,在其中给出类型:
//p3 指向一个值为42的 int 的shared_ptr shared_ptr<int> p3 = make_shared<int>(42) ; // p4指向一个值为"9999999999"的string shared_ptr<string> p4 = make_shared<string> (10,'9' ) ; // p5指向一个值初始化的(参见3.3.1节,第88 页) int,即,值为0
shared_ptr<string> p5 = make_shared<int> ();
类似顺序容器的emplace成员(,make_shared用其参数来构造给定类型的对象。例如,调用make_shared<string>时传递的参数必须与string的某个构造函数相匹配,调用make_shared<int>时传递的参数必须能用来初始化一个int,依此类推。如果我们不传递任何参数,对象就会进行值初始化。
当然,我们通常用auto定义一个对象来保存make_shared的结果,这种方式较为简单:
// p6指向一个动态分配内存的空vector auto p6 = make_shared<vector<string>>();
allocate类
用法如下:
allocator分配的内存是未构造的(unconstructed)。我们按需要在此内存中构造对象。在新标准库中,construct成员函数接受一个指针和零个或多个额外参数,在给定位置构造一个元素。额外参数用来初始化构造的对象。类似make_shared的参数。这些额外参数必须是与构造的对象的类型相匹配的合法的初始化器:
auto q = p; // q指向最后构造的元素之后的位置 alloc.construct (q++); //*q为空字符串 alloc.construct (q++,10, 'c' );// *q为cccccccccc alloc.construct (q++, "hi" ); // *q为hi!
标准库还为allocator类定义了两个伴随算法,可以在未初始化内存中创建对象。表12.8描述了这些函数,它们都定义在头文件memory 中。
类似copy,uninitialized_copy返回(递增后的)目的位置迭代器。因此,一次uninitialized_copy调用会返回一个指针,指向最后一个构造的元素之后的位置。