条款17:以独立语句将newed对象置入智能指针

127 篇文章 7 订阅
39 篇文章 3 订阅

条款17:以独立语句将newed对象置入智能指针

Store newed objects in smart pointers in standalone statements.

首先,假设我们有个函数用来显示处理函数的优先权,另一个函数用来在某动态分配所得的Widget上进行某些带有优先权的处理:

int priority();
void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);

根据“以对象管理资源”的条款,processWidget使用智能指针来对动态分配得到的Widget进行管理(即tr1::shared_ptr)

当我们试图调用processWidget:

processWidget(new Widget, priority());

需要注意的是,此时是不能通过编译的。tr1::shared_ptr构造函数需要一个原始指针(raw pointer),但是这个构造函数是一个explicit构造函数,无法进行隐式转换。因此,需要将“newWidget”的原始指针转换为processWidget所需要的tr1::shared_ptr,因此需要这样写:

processWidget(std::tr1::shared_ptr<Widget> (new Widget), priority ());

但是,虽然此时我们使用了“对象管理式资源”,仍然会产生资源的泄漏!

在编译器产生一个processWidget调用代码之前,首先需要确定把即将被传递的各个实参是什么。
在上面的代码中,第二个实参较为简单,只是一个对priority函数的调用;而第一个实参则较为复杂,对于这个实参std::tr1::shared_ptr< Widget > (new Widget),它有两部分组成:

  • 执行“new Widget”表达式
  • 调用tr1::shared_ptr构造函数

因此,在调用processWidget之前,编译器需要创建代码,做以下三件事情:

  • 调用priority
  • 执行“new Widget”
  • 调用tr1::shared_ptr构造函数

对于这三件事情,对于C++而言,“new Widget”的执行次序一定是在“tr1::shared_ptr构造函数被调用”之前,因为这个表达式的结果还需要被传递作为tr1::shared_ptr构造函数的一个实参。但是对于priority的调用而言,则是可以在第一、第二或者第三执行。假如选择在第二位执行,可以得到这样的执行序列:

  • 1,执行“new Widget”
  • 2,调用priority
  • 3,调用tr1::shared_ptr构造函数

因此,对于上面这个执行次序,如果priority的调用产生异常,此时“new Widget”返回的指针将会遗失,因为它尚未被置入tr1::shared_ptr内,而这个智能指针的存在就是为了防止资源泄漏的。因此,在对processWidget的调用过程中是会引发资源泄漏,因为在“资源被创建(经由“new Widget”)”和“资源被替换为资源管理对象”这两个时间点之间可能会被发生干扰。

为了避免这样的问题,解决办法为分离语句。即分别写出:

  • 1,创建WIdget
  • 2,将它置入一个智能指针之中,然后再将这个智能指针传给processWidget:
std::tr1::shared_ptr<Widget> pw(new Widget);    //在单独的语句内以智能指针存储newed所得对象

process(pw priority());     //这个调用动作就不会造成泄漏

之所以可以解决这个问题,是因为编译器对于“跨越语句的各项操作”没有重新排列的自由(只有在语句内它才拥有这个自由)。在上述修改后的代码中,“new Widget”表达式以及“对tr1::shared_ptr构造函数的调用”这两个动作,与“对priority的调用”是分隔开的,在不同的语句之中,因此编译器就不能再它们之间任意选择执行次序。

最后:

以独立语句将newed对象存储于(置入)智能指针内。如果不这样做,一旦异常抛出,有可能导致难以察觉的资源泄漏。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值