boost 智能指针
来源:互联网 发布:sd数据恢复免费软件 编辑:程序博客网 时间:2024/06/03 11:24
正文
1、
智能指针是一种像指针的 C++对象,但它能够在对象不使用的时候自己销毁掉。
我们知道在 C++ 中的对象不再使用是很难定义的,因此C++中的资源管理是很复杂的。各种智能指针能够操作不同的情况。当然,智能指针能够在任务结束的时候删除对象,除了在程序之外。
许多库都提供了智能指针的操作,但都有自己的优点和缺点。 Boost 库是一个高质量的开源的 C++ 模板库,很多人都考虑将其加入下一个 C++ 标准库的版本中。
Boost 提供了下面几种智能指针:
shared_ptr<T>
本指针中有一个引用指针记数器,表示类型 T 的对象是否已经不再使用。 shared_ptr
scoped_ptr<T>
当离开作用域能够自动释放的指针。因为它是不传递所有权的。事实上它明确禁止任何想要这样做的企图!这在你需要确保指针任何时候只有一个拥有者时的任何一种情境下都是非常重要的。
intrusive_ptr<T>
比
weak_ptr<T>
一个弱指针,帮助 shared_ptr
shared_array<T>
和
scoped_array<T>
和
下面让我们看一个简单的例子:
2、
scoped_ptr
例子说明:本例子使用了一个帮助我们理解的类:
下面的例子就是使用 scoped_ptr
使用普通指针
使用 scoped_ptr
void
{
}
# include
void
{
}
使用普通普通指针的时候,我们必须记住在函数退出的时候要释放在这个函数内创建的对象。当我们使用例外的时候处理指针是特别烦人的事情(容易忘记销毁它)。使用scoped_ptr
优点:对于在复杂的函数种, 使用 scoped_ptr
优点
自动释放本地对象和成员变量 [1] ,延迟实例化,操作 PIMPL 和 RAII (看下面)
缺点
在 STL 容器里,多个指针操作一个对象的时候需要注意。
性能
使用 scoped_ptr
3、
引用指针计数器记录有多少个引用指针指向同一个对象,如果最后一个引用指针被销毁的时候,那么就销毁对象本身。
shared_ptr
void
{
}
在( A )中在堆栈重创建了 CSample 类的一个实例,并且分配了一个 shared_ptr 指针。对象 mySample入下图所示:
然后我们分配了第二个指针 mySample2 ,现在有两个指针访问同一个数据。
我们重置第一个指针(将 mySample 设置为空 ),程序中仍然有一个 Csample 实例, mySample2有一个引用指针。
只要当最有一个引用指针 mySample2 退出了它的作用域之外, Csample 这个实例才被销毁。
当然,并不仅限于单个 Csample 这个实例,或者是两个指针,一个函数,下面是用 shared_ptr 的实例:
·
·
·
·
注意:如果你没有听说过 PIMPL (a.k.a. handle/body)
PIMPL :如果必须包容一个可能抛异常的子对象,但仍然不想从你自己的构造函数中抛出异常,考虑使用被叫做 HandleClass 或 Pimpl 的方法(“ Pimpl ”个双关语: pImpl 或“ pointer to implementation”)
4、
boost::shared_ptr
·
当声明或定义一个 shared_ptr<T> , T可能是一个未知的类型。例如你仅仅在前面声明了 class T ,但并没有定义 class T。当我们要释放这个指针的时候我们需要知道这个 T 具体是一个声明类型。
·
在这里本质上不需要制定 T 的类型(如从一个基类继承下来的)
·
如果你的类中自己写了释放方法,也可以使用。具体参照 Boost 文档。
·
如果你定义了一个 U* 能够强制转换到 T* (因为 T 是 U 的基类),那么shared_ptr<U> 也能够强制转换到shared_ptr<T> 。
·
(这种设计的选择超过它的优点,在多线程情况下是非常必要的)
·
5、
许多容器类,包括 STL ,都需要拷贝操作(例如,我们插入一个存在的元素到 list,vector, 或者 container。)当拷贝操作是非常销毁资源的时候(这些操作时必须的),典型的操作就是使用容器指针。
std::vector<CMyLargeClass *>vec;
vec.push_back( new CMyLargeClass("bigString") );
将内存管理的任务抛给调用者,我们能够使用 shared_ptr 来实现。
typedefboost::shared_ptr<CMyLargeClass>
std::vector<CMyLargeClassPtr>vec;
vec.push_back( CMyLargeClassPtr(new CMyLargeClass("bigString")));
当 vector 被销毁的时候,这个元素自动被销毁了。当然,除非有另一个智能指针引用了它,则还本能被销毁。让我们看Sample3 中的使用:
void
{
}
6、
使用智能指针的一些操作会产生错误(突出的事那些不可用的引用计数器,一些对象太容易释放,或者根本释放不掉)。 Boost增强了这种安全性,处理了所有潜在存在的危险,所以我们要遵循以下几条规则使我们的代码更加安全。
下面几条规则是你应该必须遵守的:
规则一:赋值和保存
规则二:_ptr<T> 不是T*
·
·
·
·
·
·
规则三:非循环引用
规则四:非临时的
7、
引用计数器是一种便利的资源管理机制,它有一个基本回收机制。但循环引用不能够自动回收,计算机很难检测到。一个最简单的例子,如下:
struct
struct
typedef
typedef
struct
{
};
struct
{
};
// a "thing" that holds a smart pointer to another "thing":
CDadPtr
CChildPtr child( new
// deliberately create a circular reference:
parent->myBoy = child;
child->myDad = dad;
// resetting one ptr...
child.reset();
如果我们调用 dad.reset(),那么我们两个对象都会失去联系。但这种正确的离开这个引用,共享的指针看上去没有理由去释放那两个对象,我们不能够再访问那两个对象,但那两个对象的确还存在,这是一种非常严重的内存泄露。如果拥有更多的这种对象,那么将由更多的临界资源不能正常释放。
A、
B、
C、
方法 A 和B 并不是一个完美的解决方案,但是可以在不使用weak_ptr 的情况下让我们使用智能指针,让我们看看 weak_ptr 的详细情况。
8、
强引用和弱引用的比较:
一个强引用当被引用的对象活着的话,这个引用也存在(就是说,当至少有一个强引用,那么这个对象就不能被释放)。boost::share_ptr就是强引用。相对而言,弱引用当引用的对象活着的时候不一定存在。仅仅是当它存在的时候的一个引用。
boost::weak_ptr<T>
struct CBetterChild : public CSample
{
};
9、
shared_ptr比普通指针提供了更完善的功能。有一个小小的代价,那就是一个共享指针比普通指针占用更多的空间,每一个对象都有一个共享指针,这个指针有引用计数器以便于释放。但对于大多数实际情况,这些都是可以忽略不计的。
intrusive_ptr
如果你要使用 intrusive_ptr
#include "boost/intrusive_ptr.hpp"
// forward declarations
class CRefCounted;
namespace boost
{
};
// My Class
class CRefCounted
{
};
// class specific addref/release implementation
// the two function overloads must be in the boost namespace onmost compilers:
namespace boost
{
} // namespace boost
10、
scoped_array
11、
从 www.boost.org 上下载最新版本的 boost,然后解压缩到你指定的目录里,解压缩后的文件目录如下:
Boost\
Doc\
Lib\
…
添加目录到我们自己的 IDE 里:
VC6 :在菜单 Tools/Options , Directories tab, "Show Directoriesfor... Include files",
VC7 :
Boost 的头文件都在 boost\ 子目录里,例如本文档例子中有 #include"boost/smart_ptr.hpp" 。所以任何人当读到年的源文件的时候就立刻知道你用到了 boost 中的智能指针。
12、
本文档中的例子里有一个子目录 boost\ 仅仅包含了本例子中使用到的一些头文件,仅仅是为了你编译这个例子,如果你需要下载完整的boost 或者获取更多的资源请到 www.boost.org。
13、
当在 VC 中使用 boost 库,或者其他库的时候会有一些小的问题。
在 Windows 的头文件中已经定义了 min
虽然 Boost 尽量处理这些问题,但有时候遇到这样的问题的时候就需要在自己的代码中加入像下面的代码在第一个 #include前加入 #define _NOMINMAX 。
#define_NOMINMAX
#include"boost/config.hpp"
usingstd::min;
using std::max;
14、
获取更多的信息,或者有问题可以查找如下资源:
·
·
·
·
·
- boost 智能指针
- Boost的智能指针
- 智能指针:boost学习
- Boost中的智能指针
- boost智能指针
- 【Boost】智能指针
- 使用Boost智能指针
- boost智能指针介绍
- Boost智能指针学习
- Boost智能指针:shared_ptr
- Boost智能指针小记
- Boost 中的智能指针
- boost:智能指针
- 使用Boost智能指针
- C++ Boost智能指针
- boost智能指针
- Boost之智能指针
- boost - 智能指针介绍
- HDU 2016 数据的交换输出
- TestComplete9下载安装
- scrollBy scrollTo使用方法
- JOGL
- 使用Visual Leak Detector检测内存…
- boost 智能指针
- 哈佛大学图书馆的20条经典训…
- SQLite语法和操作演示
- JavaScript 调用 C++
- JAVA中SERIALVERSIONUID
- WebBrowser介绍——Javascript与C++…
- Fikker 你的网站加速利器
- Fikker 怎么实现 Ajax 跨域? 怎么…
- 关于fikker反向代理服务器软件的缓…