boost 之 智能指针

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 是一种插入式的智能指针,内部不含有引用计数,需要程序员自己加入引用计数,不然编译不过。
智能指针小结:

  1. 在可以使用 boost 库的场合下,拒绝使用 std::auto_ptr,因为其不仅不符合 C++ 编程思想,而且极容易出错。
  2. 在确定对象无需共享的情况下,使用 boost::scoped_ptr 或者 boost::scoped_array (动态数组)。
  3. 在对象需要共享的情况下,使用 boost::shared_ptr 或者 boost::shared_array (动态数组)。
  4. 在需要访问 boost::shared_ptr 对象,而又不想改变其引用计数的情况下,使用 boost::weak_ptr。
  5. 最后一点,也是要求最苛刻一点:在你的代码中,不要出现 delete 或 free(C语言) 关键字,因为可以用智能指针去管理。

文章来源:
  1. C++ 智能指针详解 (单独使用命名空间标示符boost::等为了避免全部释放命名空间而造成命名污染)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值