2016-09-23 47 views
3

当在std::vector<>::emplace_back()中抛出异常时会发生什么?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对象。

这是这种情况吗?这是由标准保证的吗?

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

+1

emplace_back在引发异常时未运行... –

+0

http://en.cppreference.com/w/cpp/container/vector/emplace_back请参阅 – Hayt

+3

您必须在调用函数之前评估函数参数。构造函数首先抛出。 emplace_back从未被调用过。 –

回答

8

我期望矢量只包含第一个Foo对象。

这是这种情况吗?这是由标准保证的吗?

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

但是...

并且:莫不是任何内存泄漏?

是的,您使用的是我在Inserting into a container of smart pointers with 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,所以如果在emplace_back内发生异常,对象将被正确销毁。

+0

谢谢,和好日记顺便说一句!例如,我也不知道std :: tie。很有用 :) –

相关问题