2011-08-09 44 views
40

首先,我知道this question,但我不相信我在問同樣的事情。爲什麼不能push_back被重載來執行emplace_back的工作?

我知道什麼std::vector<T>::emplace_back確實 - 我明白爲什麼我會在push_back()以上使用它。它使用可變參數模板,允許我將多個參數轉發給新元素的構造函數。

但我不明白的是爲什麼C++標準委員會決定需要一個新的成員函數。爲什麼他們不能簡單地擴展push_back()的功能。據我所看到的,push_back可以在C++ 11超載是:

template <class... Args> 
void push_back(Args&&... args); 

這不會破壞向後兼容性,同時允許你通過N個參數,包括將調用一個正常的右值或參數複製構造函數。事實上,GCC C++ 11實現push_back()只需調用emplace_back反正:

void push_back(value_type&& __x) 
    { 
    emplace_back(std::move(__x)); 
    } 

所以,我看到它的樣子,也沒有必要爲emplace_back()。他們需要添加的是push_back()的重載,它接受可變參數,並將參數轉發給元素構造函數。

我錯了嗎?有什麼理由需要一個全新的功能嗎?

+1

這看起來類似:http://stackoverflow.com/questions/4303513/push-back-vs-emplace-back – moka

+7

好問題。 @moka他知道這兩個函數的區別。他甚至與這個特定問題聯繫在一起。 – 2011-08-09 18:06:08

+0

它們有不同的含義,在你提到你閱讀的問題中都有解釋。比如'v.emplace_back(123)'和'v.push_back(123)'例如對於'vector v;',並且從int中隱式轉換。 –

回答

38

如果T具有明確的轉換構造函數,則在emplace_backpush_back之間會有不同的行爲。

struct X 
{ 
    int val; 
    X() :val() {} 
    explicit X(int v) :val(v) {} 
}; 

int main() 
{ 
    std::vector<X> v; 
    v.push_back(123); // this fails 
    v.emplace_back(123); // this is okay 
} 

使你的建議將意味着push_back將在該實例是合法的變化,我想這是不期望的行爲。我不知道這是否是原因,但這是我能想出的唯一一件事。

+7

當處理'unique_ptr'的容器時特別有用,因爲'v.emplace_back(new foo)'比'v.push_back(std :: unique_ptr (new foo))'簡單得多。但在這種情況下,應該能夠*明確請求*轉換。 –

+0

@AlexandreC .:其實'emplace_back(new foo)'不是異常安全的,所以這是不對的。 – Mehrdad

+0

@Mehrdad你的意思是因爲可能的分配可能失敗?這是真的...... –

1

這是另一個例子。

老實說,這兩者是語義如此不同,他們的類似行爲應被視爲一個單純的巧合(由於這樣的事實,C++有「拷貝構造函數」與特定的語法)。

你真的應該使用emplace_back除非你想就地建設語義。
你很少會需要這樣的事情。一般而言,push_back就是你真正想要的語義。

#include <vector> 

struct X { X(struct Y const &); }; 
struct Y { Y(int const &); operator X(); }; 

int main() 
{ 
    std::vector<X> v; 
    v. push_back(Y(123)); // Calls Y::operator X() and Y::Y(int const &) 
    v.emplace_back(Y(123)); // Calls X::X(Y const &) and Y::Y(int const &) 
} 
相關問題