前言
智能指针的种类繁多,我听说过的就有这些:auto_ptr
、shared_ptr
、weak_ptr
、unique_ptr
、scoped_ptr
、scoped_array
、shared_array
、intrusive_ptr
,这些智能指针看起来种类繁多,但实际上常用的就只有两三种,他们是shared_ptr
、weak_ptr
和unique_ptr
,先简单了解一下这几个指针,后续再列出具体的例子和选择标准。
分类及特性
auto_ptr
这个指针历经沧桑,C++98中引入,C++11中弃用,C++17中被移除,弃用的原因主要是使用不当容易造成内存崩溃,不能够作为函数的返回值和函数的参数,也不能在容器中保存auto_ptr。
shared_ptr
据说是最好用的智能指针,使用引用计数实现,每使用它一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,自动删除所指向的堆内存。
shared_ptr
内部的引用计数是线程安全的,但是对象的读取需要加锁。weak_ptr
没有什么存在感,基本只在解除
shared_ptr
循环引用时使用,weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加,使用weak_ptr
的成员函数use_count()
可以观测资源的引用计数,使用成员函数lock()
从被观测的shared_ptr
获得一个可用的shared_ptr
对象。unique_ptr
一种比
auto_ptr
更加优秀的指针,可以唯一的拥有一个对象,auto_ptr
通过等号赋值改变所有权后,再次引用原对象会造成内存崩溃,但是unique_ptr
可以用过std::move
改变所有权,并且引用原对象会在编译时期就指出错误,同时在容器算法中也可以使用,另有一种说法是说unique_ptr
是scoped_ptr
在标准库中的一个分身。scoped_ptr
存在于boost库而非标准库中,要把资源限制在作用域里的,并且永远不能被复制,是一种轻量级的智能指针,和
const auto_ptr
很像,但是可以被reset
,并可以更加清楚地表明意图。scoped_array
跟
scoped_ptr
一样,也是独享所有权的,用于管理动态数组,不支持复制,并且初始化的时候需要使用动态数组,没有重载operator*
,需要使用get()
函数。shared_array
跟
shared_ptr
一样,内部使用了引用计数,可以复制,通过参数来传递等,需要使用动态数组来初始化。intrusive_ptr
这是一种侵入式的智能指针,内部不含有引用计数,要求被存储的对象自己实现引用计数功能,不然编译不过,还要提供
intrusive_ptr_add_ref
和intrusive_ptr_release
函数接口供intrusive_ptr
调用。
总结
- 智能指针的种类很多,但是只要掌握
shared_ptr
、weak_ptr
、unique_ptr
这三种指针的用法,就可以处理绝大多数问题。 - 智能指针的选择就根据特性来选,但是
auto_ptr
尽量不要用了,虽然历史悠久,但是毕竟由于各种诟病被抛弃了。 - 以上只给出了分类和简单特性,后续有时间会依次给出示例,指出用法和需要注意的点。