一、shared_ptr定义
c++新标准库提供了两种智能指针类型来管理动态对象。shared_ptr和unique_ptr。头文件memory。
shared_ptr允许多个指针指向同一个对象
unique_ptr则“独占”所指向的对象
智能指针是模板,要在尖括号内给出类型。
shared_ptr<string> p1;
shared_ptr<list<int>> p2;
解引用一个智能指针返回它指向的对象。如果在一个条件判断中使用智能指针,效果就是检测它是否为空。
1 | //如果p1不为空,检查它是否指向一个空string |
shared_ptr unique_ptr都支持的操作
语法 | 解释 |
---|---|
shared_ptr< T > sp | 空智能指针,可以指向类型为T的对象 |
unique_ptr< T > up | |
p | 将p用作一个条件判断,若p指向一个对象,则为true |
*p | 解引用p,获得它指向的对象 |
p->mem | 等价于(*p).mem |
p.get() | 返回p中保存的指针。要小心使用,若智能指针释放其对象,返回的指针指向的对象也消失了 |
swap(p, q) | 交换p和q的指针 |
p.swap(q) |
shared_ptr独有的操作
语法 | 解释 |
---|---|
make_shared< T > (args) | 返回一个shared_ptr,指向一个动态分配的类型为T的对象。使用args初始化次对象 |
shared_ptr< T > p(q) | p是shared_ptr q的拷贝:此操作会递增q中的计数器。q中的指针必须能转换为T* |
p = q | p和q都是shared_ptr,所保存的指针必须能相互转换。此操作会递减p的引用计数,递增q的引用计数;若p的引用计数变为0,则将其管理的原内存释放。 |
p.unique | 若p.use_count() 为1,返回true;否则返回false |
p.use_count() | 返回与p共享对象的智能指针数量;可能很慢,主要用于调试 |
make_shared函数
此函数在动态内存分配一个对象并初始化它,返回指向此对象的shared_ptr。头文件memory。
使用时要保持类型一致。
1 | //指向一个值为42的int的shared_ptr |
shared_ptr的拷贝和赋值
当进行拷贝或赋值操作时,每个shared_ptr都会记录有多少个其他shared_ptr指向相同的对象。
1 | auto p = make_shared<int> (42); //p指向的对象只有p一个引用者 |
空悬指针(dangling pointer):指向一块曾经保存数据对象但现在已经无效(被delete掉)的内存的指针。
二、shared_ptr和new结合
可以用new返回的指针来初始化智能指针。
1 | shared_ptr<double> p1; |
接受指针参数的智能指针构造函数是explicit的,不能将一个内置指针隐式转换为一个智能指针。
1 | shared_ptr<int> p1 = new int(1024); //错误:必须使用直接初始化形式 |
定义和改变shared_ptr的其他方法
语法 | 解释 |
---|---|
shared_ptr< T > p(q) | p管理内置指针q所指向的对象;q必须指向new分配的内存,且能够转换为T*类型 |
shared_ptr< T > p(u) | p从unique_ptr u那里接管了对象的所有权;将u置为空 |
shared_ptr< T > p(q, d) | p接管了内置指针q所指向的对象的所有权。q必须能转换为T*类型。p将使用可调用对象d来代替delete |
shared_ptr< T > p(p2, d) | p是shared_ptr p2的拷贝,唯一的区别是p将用可调用对象d来代替delete |
p.reset() | 若p是唯一指向其对象的shared_ptr,reset会释放次对象。若传递了可选的参数内置指针q,会令p指向q,否则会将p置为空。若还传递了参数d,讲会调用d而不是delete来释放q。 |
p.reset(q) | |
p.reset(p,d) |
不要混合使用普通指针和智能指针。
不要使用get初始化另一个智能指针或为智能指针赋值。
其他操作。reset成员经常与unique一起使用,来控制多个shared_ptr共享的对象,在改变底层对象之前,我们检查自己是否是当前对象仅有的用户。如果不是,在改变之前要制作一份新的拷贝。
1 | if(!p.unique()) |
使用d代替delete的例子。
1 | struct destination; //表示我们正在连接什么 |
unique_ptr
某个时刻只能有一个unique_ptr指向一个给定对象。当unique_ptr被销毁时,它所指向的对象也被销毁。定义一个unique_ptr时,需要将其绑定到一个new返回的指针上。1
2unique_ptr<double> p1;
unique_ptr<double> p2(new int(42));
unique_ptr不支持普通的拷贝或赋值。1
2
3
4unique_ptr<string> p1(new string("Stegosaurus"));
unique_ptr<string> p2(p1); //错误
unique_ptr<string> p3;
p3 = p2 //错误
unique_ptr操作
语法 | 解释 |
---|---|
unique_ptr< T > u1 | 空unique_ptr,可以指向类型为T的对象。u1会使用delete来释放它的指针;u2会使用一个类型为D的可调用对象来释放它的指针 |
unique_ptr < T , D > u2 | |
unique_ptr < T , D > u(d) | 空unique_ptr,可以指向类型为T的对象,用类型为D的对象d代替delete |
u = nullptr | 释放u指向的对象,将u置为空 |
u.release() | u放弃对指针的控制权,返回指针,并将u置为空 |
u.reset() | 释放u指向的对象 |
u.reset(q) | 如果提供了内置指针q,令u指向这个对象;否则将u置为空 |
u.reset(nullptr) |
1 | unique_ptr<string> p2(p1.release()); //将所有权从p1(指向String Stegosaurus)转移给p2,release将p1置为空 |
可以拷贝或赋值一个将要被销毁的unique_ptr。如下。1
2
3
4unique_ptr<int> clone(int p)
{
return unique_ptr<int>(new int(p));
}
向unique_ptr传递删除器,以shared_ptr中connection为例。
1 | void f(destination &d) |
三、weak_ptr
weak_ptr是一个 不控制所指对象生存期的智能指针,它指向由一个shared_ptr管理的对象。不会改变计数。一旦最后一个指向对象的shared_ptr被销毁,即使有weak_ptr指向对象,对象也会被释放。、
weak_ptr用法
语法 | 解释 |
---|---|
weak_ptr< T > w | 空weak_ptr可以指向类型为T的对象 |
weak_ptr< T > w(sp) | 与shared_ptr sp指向相同对象的weak_ptr。T必须能转换为sp指向的类型 |
w = p | p可以是一个shared_ptr或一个weak_ptr。赋值后w与p共享对象 |
w.reset() | 将w置为空 |
w.use_count() | 与w共享对象的shared_ptr的数量 |
w.expired() | 若w.use_count()为0,返回true,否则返回false |
w.lock() | 如果expired为true,返回一个空shared_ptr;否则返回一个指向w的对象的shared_ptr |
1 | auto p = make_shared<int>(42); |