C++ 异常 与智能指针

void func1 ( )
{
    int * p = new int(1024);
    // ... an exception occurred
    delete p;
}

上面是个很露骨的”异常不安全“的例子。

一旦发生异常,p申请的内存将得不到释放。

一个简单的办法是:

    int * p = new int(1024);
    try{
    // ... an exception occurred
    }catch(...)
    {
        delete p;
        throw;
    }
    delete p;

还有种方法是定义一个简单的类Ptr,它含有一个指针成员。该类的析构函数会释放这个指针所指对象的内存。

void func1 ( )
{
    Ptr<int> p ( new int(1024) );
    // ... an exception occurred
    // always ok
}
因为不论有没有异常发生,都要退func1的栈,p是在栈上的对象,退栈时自动调用了它的析构函数,从而释放了int的内存。

不论有没有异常发生,都要退栈;可以把这点看做类似C#的finally子句,来利用。

不过上面Ptr类只是一个示范,too naive,具体请参照C++ prmer的第13章 复制控制 管理指针成员,讲述了引用计数,和std、boost中的智能指针,会用就可以了。


不只是释放内存,对于其它的资源也是一样的,比如加锁与释放锁。

void func ( void * area)
{
    lock(area);
    // ... if an exception occurred...Oops
    unlock(area);
}
应该改为:

void func ( void * area)
{
   Locker lk ( area );
   // ...
}// lk.Locker::~Locker();
在构造函数中分配资源,在析构函数中释放。即所谓的RAII: Resource Acquisition Is Initialization   资源获取即初始化

奇怪的是C++ primer书上虽然讲了引用计数,却只介绍了不使用计数的std::auto_ptr?

std::auto_ptr的设计使它具有以下四条行为逻辑(四条限制):

1)std::auto_ptr只能保存指向动态分配对象的指针。因为std::auto_ptr本身被撤销的时候会动态释放它保存的指针所指向的内存,所以得是动态分配的。

2)不要让两个std::auto_ptr指向同一个对象,否则将来这两个std::auto_ptr被撤销的时候,那个对象被释放两次!

3)std::auto_ptr不能保存指向动态分配的数组的指针。因为std::auto_ptr中使用的是delete,而不是delete[]。

4)std::auto_ptr之间的复制和赋值被定义成了“转移式”,被转移的那个std::auto_ptr变成未绑定的。复制和赋值之后两个对象不相等,因此,不能将std::auto_ptr存储在标准库容器中。

但std::auto_ptr自C++11起,被标记为deprecated,不赞成使用的,而是用它的替代unique_ptr。

相关历史请看这儿:http://www.cppblog.com/eXile/archive/2009/11/16/101062.html

1994年. Greg Colvin向C++标准委员会提出了自己设计的智能指针:auto_ptr和counted_ptr。auto_ptr实现基本的RAII管理,不可复制;counted_ptr采用引用计数实现了一个可复制的智能指针。两者用于不同的场合。  但是标准委员会最终只通过了auto_ptr,并且对auto_ptr加入了一个古怪的“所有权转移”语义。后来auto_ptr和counted_ptr进入了Boost C++ 库,改名为scoped_ptr和shared_ptr。

std的auto_ptr与unique_ptr之间的区别:http://blog.csdn.net/weiwenhp/article/details/8708281,简言之,后者可以支持数组、可以放入容器、不支持拷贝(而是使用move语义

这里是std中的智能指针: http://en.cppreference.com/w/cpp/memory

also so see the http://msdn.microsoft.com/zh-cn/library/hh279674.aspx

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值