c++自动释放的指针之——auto_ptr和shared_ptr

假设我们使用一个用来塑模投资行为(例如股票、债券等)的程序库,其中各式各样的投资类型集成自一个root class Investment:

class Investment { ... };//"投资类型"集成体系中的root class

进一步假设,这个程序库通过一个工厂模式供应我们某特定的Investment对象:

Investment* createInvestment();
//返回指针,指向Investment继承体系内的动态分配对象。调用者有责任删除它,这里为了简化,刻意不写参数。

createInvesment的调用端使用了函数返回的对象后,有责任删除之,现在考虑有个f函数履行了这个责任:

void f()
{
    Investment* pInv = createInvesment();//调用factory函数
    。。。
    delete pInv;
}

这看起来妥当,但若干情况下f可能无法删除pInv这个指针由于函数之中有某些return语句直接结束了这个函数,那么delete就不会发生,之后我们泄露的不只是内含投资对象的那块内存,还包括那些投资对象所保存的任何资源。

为确保createInvestment返回的资源总是被释放,我们需要将资源放进对象内,当控制流离开f,该对象的析构函数会自动释放那些资源。把资源放进对象内,我们便可依赖c++的“析构函数自动调用机制”确保资源被释放。标准程序库提供的auto_ptr正是针对这种形式而设计的特制产品。auto_ptr是个“类指针对象”,也就是所谓的智能指针,其析构函数自动对其对象调用delete。下面示范如何使用auto_ptr以避免f函数潜在的资源泄露的可能性:

void f()
{
    std::auto_ptr<Investment> pInv(createInvestment());
    ...
    //调用factory函数,一如既往的使用pInv,经由auto_ptr的析构函数自动删除pInv
}

这简单的例子示范“以对象管理资源”的两个关键想法:

1、获得资源后获得立即放进管理对象内,即上述使用的auto_ptr指针,自动释放。

2、管理对象运用析构函数确保资源被释放,即自己实现一个类似auto_ptr指针的对象,在里面运用实现析构来delete

由于auto_ptr被销毁时会自动删除它所指之物,所以一定要注意别让多个auto_ptr同时指向同一对象。如果真是那样,对象会被删除一次以上,为了预防这个问题,auto_ptr有一个不同寻常的特质:

若通过copy构造函数或copy assignment操作符复制它们,它们会变成null,而复制所得的指针将取得资源的唯一拥有权!

std::auto_ptr<Investment> pInv1(createInvestment());//pInv1指向对象

std::auto_ptr<Investment> pInv2(pInv1);//pInv2指向对象,pInv1指向null

pInv1 = pInv2;pInv1指向对象,pInv2指向null

auto_ptr的代替方案是“引用技术型智慧指针”tr1::shared_ptr,它能持续追踪共有多少个对象指向某笔资源,并在无人指向它时自动删除该资源。

void f()
{
    ...
    std::trl::shared_ptr<Investment> pInv(createInvestment());
    //调用factory函数,使用pInv一如既往,经由shared_ptr析构函数自动删除pInv
    ...
}

这段代码看起来和auto_ptr那个版本相同,但shared_ptr的复制行为确实正常的,它不会因为复制而使原来的指针指向null。

问题:

auto_ptr和tr1::shared_ptr两者都在其析构中做delete而不是delete[],那意味在动态分配而得的array身上使用auto_ptr和tr1::shared_ptr是个馊主意。尽管如此,可叹的是,编译器仍能够通过编译:

std::auto_ptr<std::string> aps(new std::string[10]);//会用错误的delete形式
std::tr1::shred_ptr<int> spi(new int[1024]);//同上

综上所述:

如果打算手工释放资源(例如使用delete而非使用一个资源管理类),容易发生某些错误。灌装式的资源管理类如auto_ptr和tr1::shared_ptr往往比较轻松的遵循上面的忠告,但是这又存在着别的问题,所以就需要精巧的设计你自己的资源管理类。那并不是很困难。最后需要强调的是——咱们要学会“以对象管理资源”!!!

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值