smart_ptr简介
boost中智能指针(smart_ptr)解决了每次 new 出来的内存不需要人为delete。智能指针包括:auto_ptr,scoped_ptr,scoped_array,shared_ptr,shared_array,weak_ptr。
- 访问智能指针包含的裸指针则可以用 get() 函数。由于智能指针是一个对象,所以 if (my_smart_object) 永远为真,要判断智能指针的裸指针是否为空,需要这样判断:if (my_smart_object.get())。
- 智能指针包含了reset()方法,如果不传递参数(或者传递 NULL),则智能指针会释放当前管理的内存。如果传递一个对象,则智能指针会释放当前对象,来管理新传入的对象。
auto_ptr
std::auto_ptr 属于 STL,在 namespace std 中,包含头文件 #include<memory> 便可以使用。
std::auto_ptr 的特点:
- auto_ptr 不能共享所有权。
- auto_ptr 不能指向数组,只管理单个堆内存对象
- auto_ptr 不能作为容器的成员。
- auto_ptr 不能通过赋值操作来初始化
- auto_ptr 的 release() 函数只是让出内存所有权;如果需要释放当前管理内存,使用reset()函数
使用举例:
- std::auto_ptr<int> p(new int(42)); //OK
- std::auto_ptr<int> p = new int(42); // ERROR 这是因为auto_ptr 的构造函数被定义为了explicit
- std::auto_ptr<int> p2 = p; // p2 完全夺取了 p 的内存管理所有权,导致 p 悬空,再次使用 p 时会导致程序崩溃。(避免对auto_ptr使用赋值操作符)
scoped_ptr
boost::scoped_ptr 属于 boost 库,定义在 namespace boost 中,包含头文件 #include<boost/smart_ptr.hpp> 便可以使用。
boost::scoped_ptr 的特点:
- scoped_ptr 独享所有权,不能转换或者共享所有权
- scoped_ptr 管理单个堆内存对象,不能管理数组对象 。(由于scoped_ptr是通过delete来删除所管理对象的)
- scoped_ptr 没有 release() 方法和赋值操作符
- boost::scoped_ptr<int> p1(new int(10));
- boost::scoped_ptr<int> p2 = p1; // 编译 error: scoped_ptr 没有重载 operator=,不会导致所有权转移
scoped_array
boost::scoped_array 属于 boost 库,定义在 namespace boost 中,包含头文件 #include<boost/smart_ptr.hpp> 便可以使用。
boost::scoped_array 的特点
- scoped_array 独享所有权,不能转换或者共享所有权
- scoped_array 用于管理动态数组
- scoped_array 没有release和赋值操作符
- boost::scoped_array<int> pArr1(new int[2]); // 使用内存数组来初始化;pArr1[0],pArr1[1] 为数组中元素
- boost::scoped_array<int> pArr2 = pArr1; // 编译 error: scoped_ptr 没有重载 operator=
shared_ptr
boost::shared_ptr 属于 boost 库,定义在 namespace boost 中,包含头文件 #include<boost/smart_ptr.hpp> 便可以使用。
boost::shared_ptr 的特点:
- shared_ptr 专门用于共享所有权,其在内部使用了引用计数
- shared_ptr 用于管理单个堆内存对象的,不能指向数组
- shared_ptr 提供了一个函数 use_count(),此函数返回 boost::shared_ptr 内部的引用计数
- shared_ptr 没有 release() 函数
- boost::shared_ptr <int> p1(new int(10));
- cout << p1.use_count() << endl; // 输出结果"1"
- boost::shared_ptr <int> p2 = p1;
- cout << p2.use_count() << endl; // 输出结果"2"
shared_array
boost::shared_array 属于 boost 库,定义在 namespace boost 中,包含头文件 #include<boost/smart_ptr.hpp> 便可以使用。
boost::array_ptr 的特点:
- shared_array 专门用于共享所有权,在内部使用了引用计数。
- shared_array 用于管理动态数组
- shared_array提供了一个函数 use_count(),此函数返回 boost::shared_array 内部的引用计数
- shared_array 没有 release() 函数
使用举例:
- boost::shared_array <int> pArr1(new int[2]); //pArr1[0],pArr1[1] 为数组中元素
- cout << pArr1.use_count() << endl; // 输出结果"1"
- boost::shared_array <int> pArr2 = pArr1;
- cout << pArr2.use_count() << endl; // 输出结果"2"
weak_ptr
boost::weak_ptr 属于 boost 库,定义在 namespace boost 中,包含头文件 #include<boost/smart_ptr.hpp> 便可以使用。boost::weak_ptr 的特点:
- weak_ptr 是专门为 shared_ptr 而准备的。weak_ptr 只对 shared_ptr 进行引用,而不改变其引用计数
- 当被观察的 shared_ptr 失效后,相应的 weak_ptr 也相应失效
- weak_ptr 主要用在软件架构设计中
- 可以在基类(此处的基类并非抽象基类,而是指继承于抽象基类的虚基类)中定义一个 weak_ptr,用于指向子类的 shared_ptr
- 这样基类仅仅观察自己的 weak_ptr 是否为空就知道子类有没对自己赋值了,而不用影响子类 shared_ptr 的引用计数,用以降低复杂度,更好的管理对象。
- boost::shared_ptr <int> p1(new int(10));
- cout << p1.use_count() << endl; // 输出结果"1"
- boost::weak_ptr <int> p2 = p1;
- cout << p2.use_count() << endl; // 输出结果"1"
intrusive_ptr
boost::intrusive_ptr 属于 boost 库,定义在 namespace boost 中,包含头文件 #include<boost/smart_ptr.hpp> 便可以使用。boost::intrusive_ptr 的特点:
- intrusive_ptr 是一种插入式的智能指针,内部不含有引用计数,需要程序员自己加入引用计数,不然编译不过。
智能指针小结:
- 在可以使用 boost 库的场合下,拒绝使用 std::auto_ptr,因为其不仅不符合 C++ 编程思想,而且极容易出错。
- 在确定对象无需共享的情况下,使用 boost::scoped_ptr 或者 boost::scoped_array (动态数组)。
- 在对象需要共享的情况下,使用 boost::shared_ptr 或者 boost::shared_array (动态数组)。
- 在需要访问 boost::shared_ptr 对象,而又不想改变其引用计数的情况下,使用 boost::weak_ptr。
- 最后一点,也是要求最苛刻一点:在你的代码中,不要出现 delete 或 free(C语言) 关键字,因为可以用智能指针去管理。
文章来源:
- C++ 智能指针详解 (单独使用命名空间标示符boost::等为了避免全部释放命名空间而造成命名污染)