2016-09-23 52 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。很有用 :) –

相關問題