1.shared_ptr
1.1 智能指针也是模板类,包含在头文件<memory>中
1.2 相关操作
shared_ptr&unique_ptr都支持的操作 | 说明 |
---|---|
shared_ptr< T > | T为指向的类型 |
unique_ptr< T > | |
p | 条件判断,指向一个对象为true |
*p | 解引用获取所指对象 |
p->mem | 等价于(*p).mem |
p.get() | 返回p中保存的指针 |
swap(p,q) | 交换指针 |
p.swap(q) | |
share_ptr特有 | |
make_shared< T >(args) | 创建一个shared_ptr,类似顺序容器的emplace成员,用其args来构造给定类型的对象, 不传递参数则进行值初始化,int为0 |
shared_ptr< T > p(q) | p是shared_ptr q的拷贝 |
p = q | p的引用计数-1,q的引用计数+1 |
p.unique() | 判断p.use_count()==1?true,false |
p.use_count() | 返回共享对象的智能指针数量,可能比较慢,主要用于调试 |
1.3 不能进行内置指针到智能指针的转换,因为接受指针参数的智能指针构造函数是explicit的
shared_ptr< int > p1 = new int(1024); ×
shared_ptr< int > p2( new int(1024) ); √
1.4 定义和改变shared_ptr的其它方法
方式 | 说明 |
---|---|
shared_ptr< T > p(q) | q为内置指针 |
shared_ptr< T > p(u) | u为unique_ptr,此时u将置空 |
shared_ptr< T > p(q,d) | d为可调用对象lambda等,用来代替delete |
p.reset() | 若p为唯一指向其对象的shared_ptr,释放此对象,否则指针失效 |
p.reset(q) | q为内置指针,p指向q |
p.reset(q,d) | q为内置指针,d为可调用对象 |
1.5 尽量不要混用内置指针与智能指针
T *p = new T();
shared_ptr q(p);
当q销毁时,内存被释放,此时再使用p将产生未定义的行为。
1.6 不要使用get初始化另一个智能指针或为其赋值,会导致两个不相关的智能指针指向相同的内存对象,一方释放,会导致另一方出错,delete两次
1.7 发生异常时,智能指针会将内存释放(局部变量销毁)
2. unique_ptr
它持有对对象的独有权——两个unique_ptr不能指向一个对象,不能进行复制操作只能进行移动操作。
2.1 构造与拷贝
初始化unique_ptr必须采用直接初始化形式,且不支持拷贝或赋值,作为函数返回值除外,因为编译器知道它将被销毁。
2.2 u.release()放弃控制权,返回指针,并将u置空
2.3删除器指定与shared_ptr不一样
unique< T , decltype(fcn)* > p(new T, fcn);
3. weak_ptr
weak_ptr 是不控制所指对象生命周期的智能指针,指向shared_ptr管理的对象,并不改变shared_ptr的引用计算
3.1对象访问
由于对象可能不存在,我们不能使用weak_ptr直接访问对象,而必须调用lock,若w.expired()为true,返回一个空shared_ptr,否则返回shared_ptr。
3.2使用原因
当shared_ptr指向形成环时,引用计数一直处于≥1,无法释放各自所指的内存对象。
此时weak_ptr将发挥其优势,图左部分全为shared_ptr(强引用)此时,指针引用计数永远不会等于0,也就无法释放相应的内存空间,而右图采用weak_ptr(弱引用)不会影响引用计数,所以会释放相应的内存。