c++ - shared_ptr 构造函数的异常安全

标签 c++ shared-ptr exception-safety

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

This is exception unsafe code:

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

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

Because compiler can implement like this:

  1. run new Test
  2. call bar() <-- if bar() throws exception, the object of Test allocated by new Test cannot be deleted.
  3. call constructor of std::shared_ptr<Test>
  4. call foo()

但在这种情况下,编译器可以知道存在内存泄漏。编译器不能做 delete如果抛出异常,是否自动?

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

Test *p = new Test;

that is implemented like this:

  1. call operator new to allocate memory
  2. call constructor of Test. If constructor throws exception, memory is automatically deleted.

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

最佳答案

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

标准可以指定异常将导致 delete 在完整的所有新对象上调用 它通过的表达式。有许多历史悠久的 甚至没有考虑到这一点的原因。而今天,它会 可能会破坏太多现有代码。

该标准还可以对 表达式的评估。这会消除很多问题 未定义的行为,并使代码更具确定性(所以 测试更可靠)。从历史上看,C 没有接受这个 路由,因为它对优化有影响; C++ 保留了 规则。

关于c++ - shared_ptr 构造函数的异常安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23290770/

相关文章:

c++ - 哪些适用于 Windows 的 C++11 编译器支持新的类型特征,例如 "is_nothrow_move_constructible"?

c++ - 传递给CPP中的函数时{}是什么?

c++ - 为什么 std::shared_ptr 没有 [] 运算符?

c++ - 1000个共享指针占用多少内存?

c++ - 在 `foo` 的定义中使用 `bar::foo` ?

C++ 捕获错误并退出函数

c++ - 为后期初始化转发参数

c++ - 分配器构造和销毁成员函数是否允许从内部逻辑抛出异常?

c++ - 异常安全 C++ 共享指针