shared_ptr的构造函数的异常安全性

时间:2014-04-25 10:40:37

标签: c++ shared-ptr exception-safety

Effective C ++ 3 / E 中,我读到了这个:

  

这是异常不安全的代码:

class Test { };
void foo(const std::shared_ptr<Test> &ptr, int i);
int bar();
...

foo(std::shared_ptr<Test>(new Test), bar());
  

因为编译器可以这样实现:

     
      
  1. 运行new Test
  2.   
  3. 调用bar() &lt; - 如果bar()抛出异常,则Test分配的new Test对象无法删除。
  4.   
  5. 调用std::shared_ptr<Test>
  6. 的构造函数   
  7. 致电foo()
  8.   

但在这种情况下,编译器可以知道存在内存泄漏。如果抛出异常,编译器无法自动执行delete吗?

此外,在这种情况下,编译器会自动delete

Test *p = new Test;
  

这样实现:

     
      
  1. 致电operator new分配内存
  2.   
  3. 调用Test的构造函数。 如果构造函数抛出异常,则会自动删除内存。
  4.   

为什么编译器在第一种情况下没有做,与第二种情况不同?

1 个答案:

答案 0 :(得分:4)

编译器通常不知道存在内存泄漏。 代码从Test的构造函数返回后, 编译器必须假定该对象已完全和 正确构造,这可能(并且经常)意味着 构造函数已在某处注册了指向它的指针,并且 其他代码期望找到它。

标准可以指定异常将导致 delete将在完整的新对象上调用{{1}} 它经过的表达。有许多历史 这个原因甚至没有被考虑过。今天,它会 可能会破坏太多的现有代码。

该标准也可以对该标准实施严格的排序 表达的评价。这将消除很多问题 未定义的行为,并使代码更具确定性(所以 测试更可靠)。从历史上看,C并没有采取这种做法 路线因其对优化的影响; C ++一直保持着 规则。