在你的代码中使用Boost智能指针
Smart Pointers to boost your code(By peterchen)
翻译 masterlee
Download source files - 45.3kb
正文
智能指针能够使C++的开发简单化,主要是它能够像其它限制性语言(如C#、VB)自动管理内存的释放,而且能够做更多的事情。
智能指针是一种像指针的C++对象,但它能够在对象不使用的时候自己销毁掉。
我们知道在C++中的对象不再使用是很难定义的,因此C++中的资源管理是很复杂的。各种智能指针能够操作不同的情况。当然,智能指针能够在任务结束的时候删除对象,除了在程序之外。
许多库都提供了智能指针的操作,但都有自己的优点和缺点。Boost库是一个高质量的开源的C++模板库,很多人都考虑将其加入下一个C++标准库的版本中。
Boost提供了下面几种智能指针:
shared_ptr<T> |
本指针中有一个引用指针记数器,表示类型T的对象是否已经不再使用。shared_ptr 是Boost中提供普通的智能指针,大多数地方都使用shared_ptr。 |
scoped_ptr<T> |
当离开作用域能够自动释放的指针。因为它是不传递所有权的。事实上它明确禁止任何想要这样做的企图!这在你需要确保指针任何时候只有一个拥有者时的任何一种情境下都是非常重要的。 |
intrusive_ptr<T> |
比 shared_ptr 更好的智能指针,但是需要类型 T 提供自己的指针使用引用记数机制。 |
weak_ptr<T> |
一个弱指针,帮助shared_ptr 避免循环引用。 |
shared_array<T> |
和 shared_ptr 类似,用来处理数组的。 |
scoped_array<T> |
和 scoped_ptr 类似,用类处理数组的。 |
下面让我们看一个简单的例子:
2、 首先介绍:boost::scoped_ptr<T>
scoped_ptr 是 Boost 提供的一个简单的智能指针,它能够保证在离开作用域后对象被释放。
例子说明:本例子使用了一个帮助我们理解的类: CSample, 在类的构造函数、赋值函数、析构函数中都加入了打印调试语句。因此在程序执行的每一步都会打印调试信息。在例子的目录里已经包含了程序中需要的Boost库的部分内容,不需要下载其它内容(查看Boost的安装指南)。
下面的例子就是使用scoped_ptr 指针来自动释放对象的:
使用普通指针 |
使用scoped_ptr 指针 |
void Sample1_Plain() { CSample * pSample(new CSample);
if (!pSample->Query() ) // just some function... { delete pSample; return; }
pSample->Use(); delete pSample; } |
#include "boost/smart_ptr.h"
void Sample1_ScopedPtr() { boost::scoped_ptr<CSample> samplePtr(new CSample);
if (!samplePtr->Query() ) // just some function... return;
samplePtr->Use();
} |
使用普通普通指针的时候,我们必须记住在函数退出的时候要释放在这个函数内创建的对象。当我们使用例外的时候处理指针是特别烦人的事情(容易忘记销毁它)。使用scoped_ptr 指针就能够在函数结束的时候自动销毁它,但对于函数外创建的指针就无能为力了。
优点:对于在复杂的函数种,使用scoped_ptr 指针能够帮助我们处理那些容易忘记释放的对象。也因此在调试模式下如果使用了空指针,就会出现一个断言。
优点 |
自动释放本地对象和成员变量[1],延迟实例化,操作PIMPL和RAII(看下面) |
缺点 |
在STL容器里,多个指针操作一个对象的时候需要注意。 |
性能 |
使用scoped_ptr 指针,会增加一个普通指针。 |
引用指针计数器记录有多少个引用指针指向同一个对象,如果最后一个引用指针被销毁的时候,那么就销毁对象本身。
shared_ptr 就是Boost中普通的引用指针计数器,它表示可以有多个指针指向同一个对象,看下面的例子:
void Sample2_Shared() { // (A) 创建Csample类的一个实例和一个引用。 boost::shared_ptr<CSample> mySample(new CSample); printf("The Sample now has %i references/n", mySample.use_count()); // The Sample now has 1 references // (B) 付第二个指针给它。 boost::shared_ptr<CSample> mySample2 = mySample; // 现在是两个引用指针。 printf("The Sample now has %i references/n", mySample.use_count());
// (C) 设置第一个指针为空。 mySample.reset(); printf("The Sample now has %i references/n", mySample2.use_count()); // 一个引用
// 当mySample2离开作用域的时候,对象只有一个引用的时候自动被删除。 } |
在(A)中在堆栈重创建了CSample类的一个实例,并且分配了一个shared_ptr指针。对象mySample入下图所示:
然后我们分配了第二个指针mySample2,现在有两个指针访问同一个数据。
我们重置第一个指针(将mySample设置为空),程序中仍然有一个Csample实例,mySample2有一个引用指针。
只要当最有一个引用指针mySample2