std :: vector <> :: emplace_back()中的异常安全吗?

Jan*_*egg 5 c++ exception vector c++11 emplace

抛出异常会发生什么std::vector<>::emplace_back()

例如:

class Foo {
public:
  Foo(int bar) {
    if (bar == 4) throw std::exception("Something went wrong");
  }
}
Run Code Online (Sandbox Code Playgroud)

std::vector<std::unique_ptr<Foo>> foo_list;
foo_list.emplace_back(new Foo(3));
try {
  foo_list.emplace_back(new Foo(4));
} catch (std::exception error) {
  // How bad is it?
}
// Whats inside foo_list now?
Run Code Online (Sandbox Code Playgroud)

我希望矢量只包含第一个Foo对象.

是这样的吗?这是否由标准保证?

还有:可能有任何内存泄漏?

Jon*_*ely 9

我希望矢量只包含第一个Foo对象.

是这样的吗?这是否由标准保证?

是.上面的注释已经解释emplace_back过,甚至都没有被调用,因为Foo构造函数在初始化函数的参数时抛出.

但......

还有:可能有任何内存泄漏?

是的,您正在使用我在插入带有emplace_back(新X)的智能指针容器中描述的反模式(也发布在Overload Journal#134 - 2016年8月).

emplace_back需要重新分配向量并由于内存不足而失败时,就会出现问题.传递给函数的指针将丢失,因此您泄漏了Foo对象.这可能发生在第一次插入(Foo构造函数不抛出):

foo_list.emplace_back(new Foo(3));
Run Code Online (Sandbox Code Playgroud)

永远不要使用emplace_back将原始指针插入容器中unique_ptr,而是使用make_unique:

foo_list.emplace_back(std::make_unique<Foo>(3));
Run Code Online (Sandbox Code Playgroud)

或者如果你必须使用C++ 11然后构造unique_ptr和插入或安置,而不是原始指针:

foo_list.emplace_back(std::unique_ptr<Foo>(new Foo(3)));
Run Code Online (Sandbox Code Playgroud)

这种方式对象由一个unique_ptr立即拥有,因此如果emplace_back在对象内发生异常将被正确销毁.