标准库提供了智能指针类型来更好地管理动态对象,其行为类似常规指针,但是会负责释放所指向的对象。其中,shared_ptr允许多个指针指向同一对象;unique_ptr则“独占”所指向的对象;weak_ptr是一种弱引用,指向shared_ptr所管理的对象。
shared_ptr
如果不初始化一个智能指针,它默认是一个空指针
1 | shared_ptr<int> p; |
当进行拷贝或赋值操作时,每个shared_ptr都会记录有多少个其他shared_ptr指向相同的对象。为了说明,定义一个简单的类,使用shared_ptr控制其分配和销毁。当指向一个对象的最后一个shared_ptr被销毁时,shared_ptr类会自动销毁此对象——通过析构函数
1 | class Obj |
通过赋值,两个shared_ptr共同操作一个对象
1 | // a simple example |
输出显示为
1 | > g++ main.cc -g -o main && ./main |
包括调用函数时的参数和函数内部的局部变量,也会影响shared_ptr的计数
1 | shared_ptr<Obj> p(new Obj(12)); |
其中,foo的定义为
1 | void foo(shared_ptr<Obj> ptr) |
输出如下:
1 | > g++ main.cc -g -o main && ./main |
可以使用new返回的指针初始化智能指针。接受指针参数的智能指针构造函数是explicit的,不支持隐式转换。默认情况下,一个用来初始化智能指针的普通指针必须指向动态内存。
1 | shared_ptr<int> p = new int(1024); // error |
get()可以返回指向智能指针管理的对象的内置指针。注意,不要使用get()返回的内置指针初始化另一个智能指针,或尝试delete它
1 | shared_ptr<int> p(new int(42)); |
use_count方法返回shared_ptr的用户个数,unique方法返回是否当前指针是唯一用户
1 | shared_ptr<int> p(new int(42)); |
还可以调用自定义的可调用对象代替delete,通过shared_ptr
1 | void my_delete(Obj * po) |
输出为
1 | > g++ main.cc -g -o main && ./main |
unique_ptr
一个unique_ptr拥有它指向的对象,当我们定义一个unique_ptr时,需要将其绑定到一个new返回的指针上。且其不支持拷贝和赋值
1 | unique_ptr<double> p1; // default nullptr |
可以通过release或reset将指针所有权从一个unique_ptr转移给另一个unique_ptr。
1 | unique_ptr<Obj> p1(new Obj(12)); |
输出为
1 | > g++ main.cc -g -o main && ./main |
有一种特殊情况,即当要返回的对象将要销毁时,可以执行一种特殊的拷贝。
1 | unique_ptr<Obj> clone(int count) |
1 | > g++ main.cc -g -o main && ./main |
weak_ptr
weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr指向它。
创建weak_ptr时需要一个shared_ptr初始化。
1 | auto p = make_shared<Obj>(11); |
由于weak_ptr指向的对象可能不存在,需要调用lock函数检查weak_ptr指向的对象是否存在,如果存在则返回一个指向共享对象的shared_ptr,因此可以通过该函数使用weak_ptr访问指向的对象。