我通常在两种情况下使用auto_ptr:
1。一个函数有多处可能返回,但是需要释放开始分配的内存。例如
void FuncSample()
{
ClassOne *obj = new ClassOne;
if ( conditionOne )
{
delete obj;
return;
}
if ( conditionTwo )
{
delete obj;
return;
}
delete obj;
}
如上,如果函数一开始分配的东西比较多,则return之前要做的事情就更多。漏掉一个就会有内存泄露。当然可以用一个bool变量记录返回值让程序只
有一个返回点来修改。(我在其他文章中提到过)。如果用auto_ptr则十分简单,无需担心漏掉释放语句了。如下:
void FuncSample()
{
ClassOne *obj = new ClassOne;
std::auto_ptr< ClassOne > guard(obj);
if ( conditionOne )
{
return;
}
...
...
return;
}
2。有很多时候我们的函数需要一个指针作为参数,并且这个希望接管这个指针指向的对象。
如果我们遵循谁分配谁释放的原则,的确没有问题,但是对写代码要求就比较高,可能要找一个合适的释放时机比较难,或者就为了一个delete要添加一个
成员变量,并且这样做也很容易漏掉delete调用。反过来,如果我们new一个对象,然后把它的指针给别的函数或者对象,把释放交给它,这样既违反谁
分配谁释放的原则,也很容易产生误用。因为从函数的参数要求只是一个指针,调用者并不知道它要求是一个new 出来的对象,如果把一个零时变量的实体的
地址传进去,则会出现问题。程序要做到让人容易正确的使用,不容易错误的使用。这个时候就可以用到auto_ptr了。
示例如下:
class A
{
public:
~A()
{
for( std::list< B* >::iterator it = ptrList_.begin(); it !=
ptrList_.end(); ++it)
delete *it;
}
void TrusteePointer( B* ptr )
{
ptrList_.push_back(ptr);
}
private:
std::list< B* > ptrList_;
}
使用者如下
void FuncSample(A* a)
{
B* ptr = new B;
a->TrusteePointer(ptr);
B b;
a->TrusteePtr(&b); //错误的用法,但是编译器不知道
delete ptr; //错误的用法,ptr已经交给a去管了
//但是我们如果不delete则违背了谁分配谁释放的原则,不是那么爽。
}
如果用auto_ptr则这两个问题都能解决,修改如下:
void TrusteePointer( std::auto_ptr< B > &ptr )
{
ptrList_.push_back( ptr->release() );
}
void FuncSample(A* a)
{
B* ptr = new B;
std::auto_ptr< B >guard( ptr );
a->TrusteePointer( guard );
}