资源管理的核心目标就是确保程序动态分配的资源在使用完成后能够释放送还给系统,避免因此出现内存泄泄漏问题。正常的程序流程在末尾都会有类似delete之类的处理语句,但是不能保证之前的程序流程发生异常或者return导致后续的delete得不到执行。解决此问题的一个方法是利用C++对象使用完自动调用destructor的机制来确保自动进行资源回收。基本的思路就是RAII(Resource Acquisition Is Initialization),请求取得资源时即实行初始化,如此就可以把资源放进管理对象中。常用的有两种指针:
1. 类指针对象auto_ptr
可以如下使用:
void f()
{
std::auto_ptr pCls(CreateClassObj()); //CreateClassobj返回一个类对象指针,请求成功之后立刻初始化pCls
... .... //一些处理过程
... ... //结束时自动调用pCls的析构函数释放资源
}
为了避免重复定义类指针导致可能出现的重复删除,该种类对象指针不能有多个指向同一个资源,并且一旦发生赋值操作则源对象置为NULL,目标对象成为唯一指向资源的指针。即:
std::auto_ptr pCls-1(pCls); //pCls == NULL, pCls-1-->ClassObj
pCls = pCls-1; //pCls-1 == NULL, pCls-->ClassObj
2. 引用计数型智慧指针RCSP(reference-counting smart pointer)
有时候我们可能需要多次引用同一个资源,因此需要使用可计数的指针,每添加一个引用,count++,每释放一个引用,count--,若count == 0则释放该资源。如:
void f()
{
...
std::tr1::shared_ptr pCls(CreateClassObj());
...
}
std::tr1::shared_ptr pCls-1(pCls); //pCls, pCls-1-->ClassObj
pCls = pCls-1;
***********************************************************************************************************************************************
虽然在对象中可以较好地管理原始资源回收利用,但是由于上面使用类对象指针和RCSP返回的都是一个特定对象,因此不能直接使用其中的原始资源,而恰恰有时我们需要访问其原始资源,如:
Class-name* pObj = pCls; //Error: pCls is a Obj-Pointer not Class-name Obj-Pointer
幸好类对象指针自带了get()方法用以获得其原始数据:
Class-name* pObj = pCls.get(); //使用get()方法显示转换资源类型,安全明了
************************************************************************************************************************************************
在应用智能指针时,我们必须将newed对象通过独立的语句置于智能指针内,否则一旦抛出异常有可能导致难以察觉的资源泄漏。如:
processWidget(std::tr1::shared_ptr(new Widget), priority());
智能指针和priority()的返回值共同作为processWidget()的参数,第一个肯定要首先new Widget,第二步则不确定,比如先执行了priority()最后执行shared_ptr的初始化操作。若priority()抛出异常,则会导致智能指针无法正常初始化,因此导致内存泄漏。应当将智能指针部分独立写出,再讲shared_ptr作为函数参数传入,避免执行顺序不规范导致的问题。
阅读(3992) | 评论(0) | 转发(2) |