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

c++ exception safety in constructor

本文关键字:异常 安全 c++ 构造函数      更新时间:2023-10-16

下面的代码怎么样

MyClass a(new Foo(), new Bar());

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

正在进行

std::unique_ptr<Foo>

std::shared_ptr<Foo>

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

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

是的。

以[…]为参数是否足以防止泄漏?

不一定。这取决于如何传递参数。例如,即使假设你的类构造函数是这样的:

MyClass::MyClass(std::unique_ptr<Foo> foo, std::unique_ptr<Bar> bar)

以下情况仍可能导致泄漏:

MyClass a(std::unique_ptr<Foo>(new Foo()), std::unique_ptr<Bar>(new Bar())

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

  1. 对表达式new Foo()求值
  2. 对表达式new Bar()求值
  3. 根据1的结果构造临时std::unique_ptr<Foo>
  4. 根据2的结果构造std::unique_ptr<Bar>临时

如果2)抛出异常,则表示您丢失了Foo

然而,使用std::make_unique<>()(仅限C++14)或std::make_shared<>()(如)可以使其安全

MyClass a(std::make_unique<Foo>(), std::make_unique<Bar>());

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