2015-04-12 44 views
1

爲什麼公共構造函數(和析構函數)不能將一個類型爲T的對象置於向量的後面?以下片段格式不正確。爲什麼類型T要放在一個向量的末尾需要移動才能構造?

#include <vector> 

struct Foo { 
    Foo() {} 
    Foo(int) {} 
    ~Foo() {} 

    Foo(const Foo&) = delete; 
    Foo& operator=(const Foo&) = delete; 
}; 

int main() { 
    std::vector<Foo> vfoo(10); 

    vfoo.emplace_back(); 
} 

emplace_back要求Foo至少可移動構造的,而這個代碼無法編譯,因爲移動構造函數與拷貝構造函數一起被刪除。但我想象emplace_back使用placement new調用默認構造函數。

+4

當容器大小調整並且需要複製現有內容時,您會發生什麼? –

+0

請參閱http://en.cppreference.com/w/cpp/container/vector/emplace上的「參數」下的「類型要求」 – o11c

+0

@ o11c「emplace」和「emplace_back」是不同的東西,無論如何,問題這就是爲什麼有這樣的要求,而不是要求是什麼。 –

回答

6

在您的示例中,該向量由10元素構造而成。

然後你添加一個。如果capacity()中沒有更多的空間,則必須分配一個新的緩衝區,已經存在的10個元素必須移入它,然後添加新的元素。

你會發現上面的單詞move - 這就是爲什麼你需要移動ctor。

此外,即使您沒有元素,或者您仔細確保有足夠的容量,編譯器也無法知道:移動現有元素的代碼將被編譯(如果不運行),您將獲得你的錯誤。

從「vector」中缺少一個「推回,並且我保證已有容量」的方法。加上「設定容量,放棄任何現有元素」,可以讓您添加元素而不需要移動ctor(或複製ctor後備)。在發明emplace之前,所有添加元素都需要拷貝或移動:直到C++ 11全部添加元素都需要拷貝。缺乏這兩種具有奇怪語義的方法只是爲了讓一個不可移動的類型有限地使用vector並不奇怪。我鼓勵你編寫一個有兩個擴展(或類似的東西)的容器,並建議將它添加到C++中:它也可能有助於高性能用例(編譯器在證明我確實確保容量是足以我的經驗)。

+0

是否可以刪除Moveable需求,並且如果對象不可移動但需要重新分配,則會發出'emplace_back'? (或者,如果我們不想改變那個,使用不同名稱的新emplace函數) –

+0

@MattMcNabb絕對需要單獨的函數。就我所知,不可能準確地檢測出是否有'MoveInsertable'。 –

+1

@ T.C。但是,你可以準確地檢測到它(但實際上移動的事實不能確定,但​​不強制這似乎是合理的?)還是還有更多? (我猜分配器失敗的時間晚了?) – Yakk

相關問題