简介

boost::scoped_ptr是一个比较简单的智能指针,它能保证在离开作用域之后它所管理对象能被自动释放。下面这个例子将介绍它的使用:

 1 #include <iostream>2 #include <boost/scoped_ptr.hpp>3 4 using namespace std;5 6 class Book7 {8 public:9     Book()
10     {
11         cout << "Creating book ..." << endl;
12     }
13
14     ~Book()
15     {
16         cout << "Destroying book ..." << endl;
17     }
18 };
19
20 int main()
21 {
22     cout << "=====Main Begin=====" << endl;
23     {
24         boost::scoped_ptr<Book> myBook(new Book());
25     }
26     cout << "===== Main End =====" << endl;
27
28     return 0;
29 }

运行结果:

可以看出:当myBook离开了它的作用域之后,它所管理的Book对象也随之销毁。

特点——不能共享控制权

scoped_ptr不能通过其他scoped_ptr共享控制权,因为在scoped_ptr类的内部将拷贝构造函数=运算符重载定义为私有的。我们看下scoped_ptr类的定义就清楚了:

 1 namespace boost2 {3     template<typename T> class scoped_ptr : noncopyable4     {5     private:6 7         T *px;8 9         scoped_ptr(scoped_ptr const &);
10         scoped_ptr &operator=(scoped_ptr const &);
11
12         typedef scoped_ptr<T> this_type;
13
14         void operator==( scoped_ptr const & ) const;
15         void operator!=( scoped_ptr const & ) const;
16     public:
17         explicit scoped_ptr(T *p = 0);
18         ~scoped_ptr();
19
20         explicit scoped_ptr( std::auto_ptr<T> p ): px( p.release() );
21         void reset(T *p = 0);
22
23         T &operator*() const;
24         T *operator->() const;
25         T *get() const;
26
27         void swap(scoped_ptr &b);
28     };
29
30     template<typename T>
31     void swap(scoped_ptr<T> &a, scoped_ptr<T> &b);
32 }

下面这段代码中的注释部分打开会造成编译失败:

 1 #include <iostream>2 #include <boost/scoped_ptr.hpp>3 4 using namespace std;5 6 class Book7 {8 public:9     Book()
10     {
11         cout << "Creating book ..." << endl;
12     }
13
14     ~Book()
15     {
16         cout << "Destroying book ..." << endl;
17     }
18 };
19
20 int main()
21 {
22     cout << "=====Main Begin=====" << endl;
23     {
24         boost::scoped_ptr<Book> myBook(new Book());
25         //boost::scoped_ptr<Book> myBook1(myBook);    // Error: scoped_ptr的拷贝构造函数私有
26         //boost::scoped_ptr<Book> myBook2 = myBook;   // Error: scoped_ptr的=运算符重载私有
27     }
28     cout << "===== Main End =====" << endl;
29
30     return 0;
31 }

所以,scoped_ptr不能用在标准库的容器中,因为容器中的push_back操作需要调用scoped_ptr的=运算符重载函数,结果就是会导致编译失败。

 1 #include <iostream>2 #include <string>3 #include <vector>4 #include <boost/scoped_ptr.hpp>5 6 using namespace std;7 8 class Book9 {
10 private:
11     string name_;
12
13 public:
14     Book(string name) : name_(name)
15     {
16         cout << "Creating book " << name_ << " ..." << endl;
17     }
18
19     ~Book()
20     {
21         cout << "Destroying book " << name_ << " ..." << endl;
22     }
23 };
24
25 int main()
26 {
27     cout << "=====Main Begin=====" << endl;
28     {
29         boost::scoped_ptr<Book> myBook(new Book("「1984」"));
30         vector<boost::scoped_ptr<Book>> vecScoped;
31         //vecScoped.push_back(myBook);   // Error: push_back操作内部调用了scoped_ptr的=运算符重载函数
32     }
33     cout << "===== Main End =====" << endl;
34
35     return 0;
36 }

编译检查=万无一失?

虽然我们无法通过scoped_ptr的拷贝构造函数和=运算符重载函数共享控制权。那如果将一个对象交给多个scoped_ptr来管理会怎样?

 1 #include <iostream>2 #include <boost/scoped_ptr.hpp>3 4 using namespace std;5 6 class Book7 {8 public:9     Book()
10     {
11         cout << "Creating book ..." << endl;
12     }
13
14     ~Book()
15     {
16         cout << "Destroying book ..." << endl;
17     }
18 };
19
20 int main()
21 {
22     cout << "=====Main Begin=====" << endl;
23     {
24         Book * book = new Book();
25         boost::scoped_ptr<Book> myBook(book);
26         boost::scoped_ptr<Book> myBook1(book);
27     }
28     cout << "===== Main End =====" << endl;
29
30     return 0;
31 }

我们发现编译没报错,但是运行时出错了,如下:

之所以会这样是因为每个scoped_ptr对象都保存了自己所管理对象指针px,scoped_ptr对象在离开自己作用域时会调用了自身的析构函数,在析构函数内部会调用delete px,当多个scoped_ptr管理同一个对象时,那么在它们离开作用域之后,势必会多次调用delete以释放它们所管理的对象,从而造成程序运行出错。

其他接口

虽然scoped_ptr不能转移控制权,但是它们可以交换共享权。就以下面的代码举个例子:

 1 #include <iostream>2 #include <string>3 #include <boost/scoped_ptr.hpp>4 5 using namespace std;6 7 class Book8 {9 private:
10     string name_;
11
12 public:
13     Book(string name) : name_(name)
14     {
15         cout << "Creating book " << name_ << " ..." << endl;
16     }
17
18     ~Book()
19     {
20         cout << "Destroying book " << name_ << " ..." << endl;
21     }
22 };
23
24 int main()
25 {
26     cout << "=====Main Begin=====" << endl;
27     {
28         boost::scoped_ptr<Book> myBook(new Book("「1984」"));
29         boost::scoped_ptr<Book> myBook1(new Book("「A Song of Ice and Fire」"));
30         myBook.swap(myBook1);
31     }
32     cout << "===== Main End =====" << endl;
33
34     return 0;
35 }

运行结果:

根据栈的特性,应该是后面构造的scoped_ptr对象先销毁(从而销毁了它们所管理的对象),正是因为我们对两个智能指针的控制权进行交换之后,才出现了这种相反的结果。

此外,在scoped_ptr离开作用域之前也是可以显式销毁它们所管理的对象的。调用它的reset方法即可。请看下面例子:

 1 #include <iostream>2 #include <string>3 #include <boost/scoped_ptr.hpp>4 5 using namespace std;6 7 class Book8 {9 private:
10     string name_;
11
12 public:
13     Book(string name) : name_(name)
14     {
15         cout << "Creating book " << name_ << " ..." << endl;
16     }
17
18     ~Book()
19     {
20         cout << "Destroying book " << name_ << " ..." << endl;
21     }
22 };
23
24 int main()
25 {
26     cout << "=====Main Begin=====" << endl;
27     {
28         boost::scoped_ptr<Book> myBook(new Book("「1984」"));
29         myBook.reset();
30         cout << "After reset ..." << endl;
31     }
32     cout << "===== Main End =====" << endl;
33
34     return 0;
35 }

运行结果:

可以看出:程序在输出“After reset ...”之前已经完成了对所管理对象的释放。

总结(摘自《超越C++标准库:Boost库导论》)

使用裸指针来写异常安全和无错误的代码是很复杂的。使用智能指针来自动地把动态分配对象的生存期限制在一个明确的范围之内,是解决这种问题的一个有效的方法,并且提高了代码的可读性、可维护性和质量。scoped_ptr明确地表示被指物不能被共享和转移。当一个动态分配的对象被传送给 scoped_ptr, 它就成为了这个对象的唯一的拥有者。因为scoped_ptr几乎总是以自动变量或数据成员来分配的,因此它可以在离开作用域时正确地销毁,从而在执行流由于返回语句或异常抛出而离开作用域时,总能释放它所管理的内存。

在以下情况时使用scoped_ptr:

  • 在可能有异常抛出的作用域里使用指针
  • 函数里有几条控制路径
  • 动态分配对象的生存期应被限制于特定的作用域内
  • 异常安全非常重要时(始终如此!)

参考

  • http://www.cnblogs.com/sld666666/archive/2010/12/16/1908265.html
  • Björn Karlsson:Beyond the C++ Standard Library: An Introduction to Boost(《超越C++标准库:Boost库导论》)

(完)

Boost智能指针——boost::scoped_ptr(使用及原理分析)相关推荐

  1. Boost智能指针——shared_ptr

    boost::scoped_ptr虽然简单易用,但它不能共享所有权的特性却大大限制了其使用范围,而boost::shared_ptr可以解决这一局限.顾名思义,boost::shared_ptr是可以 ...

  2. 在你的代码中使用Boost智能指针

    在你的代码中使用Boost智能指针 Smart Pointers to boost your code(By peterchen)  翻译 masterlee Download source file ...

  3. C++“准”标准库Boost学习指南(1):智能指针Boost.smart_ptr

    我们学习C++都知道智能指针,例如STL中的std::auto_ptr,但是为什么要使用智能指针,使用它能带给我们什么好处呢? 最简单的使用智能指针可以不会因为忘记delete指针而造成内存泄露.还有 ...

  4. Boost智能指针——weak_ptr

    循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理循环引用的对象.一个简单的例子如下: #include <string> #include <ios ...

  5. boost智能指针之shared_ptr,scoped_ptr,intrusive_ptr,weak_ptr源码简析

    boost库实现了各种智能指针,基本上都纳入了c++11标准中,boost库的smart_ptr目录下就是各种指针的实现了: 1.shared_ptr template<class T> ...

  6. [转] Boost智能指针——scoped_ptr

    http://www.cnblogs.com/tianfang/archive/2008/09/15/1291050.html boost::scoped_ptr和std::auto_ptr非常类似, ...

  7. Boost智能指针——scoped_ptr

    boost::scoped_ptr和std::auto_ptr非常类似,是一个简单的智能指针,它能够保证在离开作用域后对象被自动释放.下列代码演示了该指针的基本应用: #include<stri ...

  8. boost any 实现万能容器_全面剖析 C++ Boost 智能指针!| CSDN 博文精选

    作者 | .NY&XX 责编 | 屠敏 出品 | CSDN 博客 为什么要使用智能指针 C++没有提供类似JAVA的垃圾回收机制,因此Boost可以通过智能指针来管理内存避免一些问题.C++继 ...

  9. 全面剖析 C++ Boost 智能指针! | CSDN 博文精选

    作者 | .NY&XX 责编 | 屠敏 出品 | CSDN 博客 为什么要使用智能指针 C++没有提供类似JAVA的垃圾回收机制,因此Boost可以通过智能指针来管理内存避免一些问题.C++继 ...

最新文章

  1. 冬眠动物克服肌肉萎缩,靠的居然是“肠子”|Science
  2. 【机器学习】基于opencv实现目标检测,error LNK2001: unresolved external symbol public: virtual bool CvSVM::train...
  3. [攻防世界 pwn]——welpwn
  4. 以太网和路由设置,内网和外网同时上
  5. 批量重命名文件和批量修改文件扩展名
  6. C++基础与深度解析第二章:对象与基本类型
  7. Windows XP Nlite 2007珍藏版 BY 丘比特
  8. 计算机桌面底边出现库如何去掉,Win7电脑桌面图标有蓝底如何去掉?
  9. oracle查询是否包含英文字符串,oracle字符串载取及判断是否包含指定字符串
  10. 电源防反接和防倒灌 - 使用MOS 管和运放实现理想二极管
  11. Advanced Download Manager(ADM) – 来自俄罗斯的 Android 下载神器,支持下载 BT 种子
  12. WRDS卓越学者和沃顿研究数据与分析图书馆员会议在北京宾大沃顿中国中心举行:庆祝研究、思想领导力和全球合作方面的创新
  13. VC++中的WinMain()函数介绍
  14. oracle dba_waiters中的lockid是什么,Oracle 锁机制学习
  15. 收集前端优秀的网站、博客、书籍
  16. SDNU 1221
  17. linux设置nexus开机自启动_linux nexus自启动
  18. Spring简化Java开发_java开发如何用spring简化?详细图解
  19. Java插入排序(思路及实现)
  20. react-react ssr

热门文章

  1. linux的apache2.4限定某个目录禁止解析PHP及user_agent与PHP相关配置
  2. iperf测试网卡性能
  3. asp.net 浏览服务器文件
  4. 挂“洋头”卖奶粉,澳优还要欺骗好久
  5. Android Service学习之AIDL, Parcelable和远程服务
  6. String.getBytes(Unicode)的疑问 以及 SHIFT-JIS编码范围
  7. 慎用Hyper-Threading Technology
  8. 数据类型转换规则C语言
  9. InputStream 、 InputStreamReader和BufferedReader
  10. 架构师一般做到多少岁_软件测试可以做到多大岁数?