使用RAII技术来管理资源

        我们考虑以下的代码:

void func(){
   Book* ptr = new Book();
   ......
   delete ptr; //一定会执行到这里吗?
}
        这是很常见的代码,它看起来或许妥当,但是在若干情况下我们无法释放ptr所指向的对象。或许开发人员在“......”区域添加了一个过早的return语句,如果这样一个return被执行起来,那么控制流就一定不会触碰delete语句。亦或是“......”区域内的语句抛出异常,果真如此的话delete语句还是不会被执行。总而言之,这样的代码不安全。而要解决这样的问题,我们需要RAII技术。

        C++中RAII的全称是“Resource acquisition is initialization”,直译为“资源获取即初始化”。RAII的核心思想是将资源和对象的生命周期捆绑起来,对象创建获取资源,对象销毁释放资源。简单来说就是使用对象来管理资源,也就是创建一个对象并将资源的生命周期和对象的生命周期相关联,如此一来就可以用对象的管理设施来管理资源。最简单的RAII形式是,创建这样一个对象:其构造函数获取这份资源,析构函数释放这份资源。

class Book{......};
class BookHandle{
public:
   Explicit BookHandle(Book* bk): book(bk){}
   ~BookHandle(){delete book;}
   Book* get(){return book;}
private:
   BookHandle(const Book&);
   BookHandle& operator=(const Book&);
   Book* book;
};
        BookHandle的好处在于我们可以不用理会控制流如何离开区块,一旦对象被销毁(离开作用区域),其析构函数自然会被调用,于是资源被释放。如果资源释放可能会抛出异常,这或许有些麻烦,但是前面我们已经讨论过此问题,便不用担心了。因此上面的代码会发生以下的变化:

void func(){
   BookHandle bh(new Book());
   ......  //不用担心控制流如何离开
   //bh的析构函数释放资源
}
        但是也有一种情况使得RAII也变得不安全,那就是将RAII对象分配到堆上时。这时只有显示的使用delete来删除BookHandle对象才能让BookHandle对象的析构函数来释放其所包含的对象。

BookHandle* bh = new BookHandle(new Book());  //糟糕的主意
        两个常用的RAII classes的对象是shared_ptr和auto_pt,前者通常是较好的选择。但是并非所有的资源都是heap-based,对于那种资源来说,像auto_ptr和shared_ptr往往不适合作为资源掌握者。既然如此,你可能需要建立自己的RAII calsses。对此还要注意它的copying的行为。一般而言,我们不允许对RAII class进行copy。但是事无绝对,如果你非要如此的话,请记住要对其进行深度拷贝。还要注意,每一个RAII class都应该提供一个“取得其所管理之资源”的办法。对原始资源的访问可能经由显示转换或隐式转换。显示转换比较安全,但隐式转换对客户比较方便。         



        

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值