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

《Effective C++ 中文版 第三版》读书笔记

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

proToby(std::tr1::shared_ptr(new Widget), priority());

在调用 proToby 之前,编译器必须创建代码,做以下三件事:

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

C++ 编译器会以什么样的顺序完成这些事情呢?弹性很大。这和其他语言如 Java 和 C# 是不同的,后两者总是以特定的次序完成函数参数的构造。可以确定的是 “new Widget” 一定执行于 tr1::shared_ptr 构造函数被调用之前,因为这个表达式的结果还要被传递作为 tr1::shared_ptr 构造函数的一个实参,但是对调用 priority 则可以排在第一、第二或者第三位执行。若编译器,恰巧把调用 priority 排在了第二位。最终获得这样的操作序列:

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

现在想一个问题:万一对 priority 的调用导致异常,会发生什么事?此时,“new Widget” 返回的指针将会遗失,因为他未被置入 tr1::shared_ptr 内,后者是我们用来期盼用来方位资源泄漏的武器。但是从这个可能的情况中,我们发现:在对 proToby 的调用过程中可能引发资源泄漏,因为在“资源被创建(经由 “new Widget”)”和“资源被转换为资源管理对象”两个时间点之间有可能发生异常干扰。

避免的办法:使用分离语句,分别写出(1)创建 Widget,(2)将它置入一个智能指针内,然后再把那个智能指针传给 proToby:

std::tr1::shared_ptr pT(new Widget);
proToby(pT,priority());

这样之所以可行,因为编译器对于“跨越语句的各项操作”没有重新排列的自由(只有在语句内他才有这个自由)。

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

你可能感兴趣的:(条款 17:以独立语句将 newed 对象置入智能指针)