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

时间:2013-06-28 00:21:05

标签: c++ exception c++11 shared-ptr unique-ptr

如何遵循以下代码

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

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

正在服用

std::unique_ptr<Foo>

std::shared_ptr<Foo>

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

1 个答案:

答案 0 :(得分:5)

  

如果“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>临时值。
  5. 如果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<>())会立即将他们创建的对象关联到相应的智能指针,而不需要这两个操作(动态分配和构建智能指针)与任何其他操作交错。