文章目录
- auto_ptr
- unique_ptr
- shared_ptr
- weak_ptr
- 参考
auto_ptr
auto_ptr是C++11前标准库提供的一种智能指针,它具有unique_ptr的部分特性,但不是全部。特别是,我们不能在容器中保存auto_ptr,也不能从函数中返回auto_ptr。
其功能如下:
- 支持拷贝构造
- 支持赋值拷贝
- 支持operator->/operator*解引用
- 支持指针变量重置
- 保证指针持有者唯一
它最大的限制是,为了保证所有权唯一,在拷贝复制后,会将原auto_ptr中管理的指针置空,此时再次操作原auto_ptr会导致空指针。这违反了赋值操作通常不改变源对象的常规预期。
例子:
int *pi = new int(3);std::auto_ptr<int> ap(pi);std::auto_ptr<int> bp = ap;std::cout << *bp << std::endl;std::cout << *ap << std::endl; // 空指针std::cout << *pi << std::endl;
运行结果:
3
Segmentation fault (core dumped)
因此,在C++11中被弃用,并最终在c++17中移除出去。
unique_ptr
unique_ptr提供了一种严格的所有权语义:
- 一个unique_ptr拥有一个对象,它保存一个指针指向该对象。即,unique_ptr有责任用所保存的指针销毁所指向的对象
- unique_ptr不能拷贝(没有拷贝构造函数和拷贝赋值操作),但可以移动
- unique_ptr保存一个指针,当他自身被销毁时,使用关联的释放器(如果有的话)释放所指向的对象(默认版本使用delete来释放)
unique_ptr的用途包括:
- 为动态分配的内存提供异常安全
- 将动态分配内存的所有权传递给函数
- 从函数返回动态分配的内存
- 在容器中保存指针
我们可以将unique_ptr理解为一个简单指针(“包含指针”)或(如果有释放器的话)一对指针:
C++11标准库没有提供类似make_shared()的创建unique_ptr和函数make_unique,但是在c++14后便准库提供了,基本实现:
template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args )
{unique_ptr<T>(new T(std::forward<Args>(args)...))
}
shared_ptr
shared_ptr表示共享所有权。shared_ptr是一种计数指针,当计数变成0时释放所指向的对象。可以将shared_ptr理解为包含两个指针的结构:一个指针指向对象,一个指针指向计数器:
释放器deleter用来在计数器变成0时释放共享对象。默认释放器通常是delete(调用对象的析构函数并释放自由存储空间)。
shared_ptr的一些限制:
- shared_ptr的循环链表会导致资源泄漏,使用weak_ptr可以打破循环
- 比起限定作用域的对象,共享所有权的对象会保持更长时间的活跃(因此会导致更高的平均资源占用)
- 多线程环境中的共享指针代价很高(因为要防止使用计数上的数据竞争)
- 共享对象析构函数的执行时间不可预测,共享对象的更新算法/逻辑比普通对象的相应算法/逻辑更容易出错。
- 如果单一(最后的)结点保持一个大数据结构活跃,释放它所导致的析构函数层叠调用会导致严重的“垃圾收集延迟”,不利于实时响应。
当可以选择时:
- 优先选择unique_ptr而不是shared_ptr
- 优先选择普通限域对象而不是在堆中分配空间、由unique_ptr管理所有权的对象。
weak_ptr
weak_ptr指向一个shared_ptr所管理的对象。为了访问对象,可使用成员函数lock()将weak_ptr转换为shared_ptr。weak_ptr允许访问他人拥有的对象:
- 仅当对象存在时你才需要访问它
- 对象可能在任何时间被(其他人)释放
- 在对象最后一次被使用后必须调用其析构函数(通常释放非内存资源)
可以将一个weak_ptr理解为两个指针:一个指针指向(可能是共享的)对象,另一个指针指向此对象的shared_ptr的使用计数:
若使用计数器用来保持使用计数结构活跃,因为在对象的最后一个shared_ptr的声明期结束后,仍可能有weak_ptr活跃。
对weak_ptr而言,为了访问它的对象,必须将它转换成shared_ptr。
参考
auto_ptr
weak_ptr
shared_ptr
unique_ptr
cpp11新特性之智能指针(上):关于auto_ptr的一切
cpp11新特性之智能指针(下):深入理解现代cpp中的智能指针shared_ptr、unique_ptr 以及 weak_ptr