5

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

例如:

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

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?

我希望向量只包含第一个 Foo 对象。

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

还有:会不会有内存泄漏?

4

1 回答 1

10

我希望向量只包含第一个 Foo 对象。

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

是的。上面的评论已经解释过,emplace_back甚至永远不会被调用,因为Foo构造函数在初始化函数的参数时抛出。

但 ...

还有:会不会有内存泄漏?

是的,您正在使用我在使用 emplace_back(new X) 插入智能指针容器中描述的反模式(也发表在Overload Journal #134 - August 2016中)。

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

foo_list.emplace_back(new Foo(3));

切勿使用emplace_back将原始指针插入 的容器unique_ptr,而是使用make_unique

foo_list.emplace_back(std::make_unique<Foo>(3));

或者,如果您必须使用 C++11,则构造unique_ptr并插入或放置它,而不是原始指针:

foo_list.emplace_back(std::unique_ptr<Foo>(new Foo(3)));

这样,对象unique_ptr立即被 a 拥有,因此如果emplace_back对象内部发生异常,将被正确销毁。

于 2016-09-23T14:00:06.810 回答