构造函数中的c ++异常安全性

Gam*_*per 6 c++ exception shared-ptr unique-ptr c++11

怎么样下面的代码

MyClass a(new Foo(), new Bar());
Run Code Online (Sandbox Code Playgroud)

如果"new Foo()"成功,但"new Bar()"抛出,Foo会泄漏吗?

正在服用

std::unique_ptr<Foo>
Run Code Online (Sandbox Code Playgroud)

要么

std::shared_ptr<Foo>
Run Code Online (Sandbox Code Playgroud)

作为参数,足以防止泄漏?

And*_*owl 6

如果"new Foo()"成功,但"new Bar()"抛出,Foo会泄漏吗?

是.

以[...]为参数,足以防止泄漏?

不必要.这取决于您如何传递参数.例如,即使你认为你的类构造函数如下所示:

MyClass::MyClass(std::unique_ptr<Foo> foo, std::unique_ptr<Bar> bar)
Run Code Online (Sandbox Code Playgroud)

以下可能仍会导致泄漏:

MyClass a(std::unique_ptr<Foo>(new Foo()), std::unique_ptr<Bar>(new Bar())
Run Code Online (Sandbox Code Playgroud)

这是因为可以允许编译器按以下顺序评估上述表达式:

  1. 评估表达式 new Foo()
  2. 评估表达式 new Bar()
  3. std::unique_ptr<Foo>从结果1 构造临时.
  4. std::unique_ptr<Bar>从2的结果构造临时.

如果2)抛出异常,你就失去了Foo.

但是,通过使用std::make_unique<>()(仅限C++ 14)或者std::make_shared<>()像这样可以使这个安全:

MyClass a(std::make_unique<Foo>(), std::make_unique<Bar>());
Run Code Online (Sandbox Code Playgroud)

现在不会发生泄漏,因为std::make_unique<>()(和std::make_shared<>())立即将它们创建的对象与相应的智能指针相关联,而这两个操作(动态分配和智能指针的构造)与任何其他操作交错.