2012-07-20 71 views
17

假設我有以下代碼:移動與向量::的push_back

#include <vector> 
struct A { 
    int a; 
    int x; 
}; 
int main() { 
    using namespace std; 
    A a1; 
    A a2; 
    vector<A> va; 
    va.push_back(a1); 
    va.push_back(move(a2)); 
} 

我知道的std ::向量的元素被連續存儲,不像一個std ::名單。在上面的代碼a2被移動,但真的沒有a2複製到矢量vava.push_back(a2);和有何區別?

+2

在你的情況下,'std :: move'ing'a2'確實是* nothing *,因爲它是一個平面類型(即它沒有外部數據)並且仍然會複製。 – Xeo 2012-07-20 03:59:26

+0

@cdhowie謝謝。糾正。 – ggg 2012-07-20 04:01:55

+0

您可能想閱讀[可以請某人解釋移動語義給我?](http://stackoverflow.com/questions/3106110/)的移動語義介紹。 – fredoverflow 2012-07-20 07:45:53

回答

26

就你而言,沒有有效的區別,因爲你使用的是編譯器提供的拷貝構造函數。使用可移動構建的對象時,您會看到明顯的性能差異,並需要花費大量的精力進行復制。在這種情況下,使用push_back(x)將創建該對象的副本,而push_back(move(x))會告知push_back()它可能「竊取」x的內容,使x處於不可用和未定義狀態。

考慮如果您有一個列表向量(std::vector<std::list<int> >),並且您想推送包含100,000個元素的列表。沒有move(),整個列表結構和所有100,000個元素將被複制。有了move(),一些指針和其他一小部分數據就會被打亂,就是這樣。這將更快,並且需要更少的整體內存消耗。

+1

爲什麼?移動C-tor會自動生成,不是這樣嗎? – ForEveR 2012-07-20 04:09:30

+6

@ForEveR無論是否自動生成都沒關係,因爲在可以移動的'A'結構中沒有分配。你只有兩個'int's,移動構造函數將執行與複製構造函數相同的操作:將源對象上的ints中存儲的值分配給新對象。在這種類型的移動場景中不可能進行優化,因爲它已經儘可能優化了。 – cdhowie 2012-07-20 04:11:08

+0

@cdhowie所以在移動過程中總會有東西被複制? – ggg 2012-07-20 04:39:02

14

當您使用va.push_back(a2)版本vector<T>::push_back(const T&)將被調用,當您使用va.push_back(move(a2))版本vector<T>::push_back(T&&)將被稱作......

但在你的情況下,有對性能比較沒有什麼區別,因爲

15隱式定義的複製/移動構造函數,用於非工會類 X對其基礎和成員執行成員複製/移動。

段落12.8 n3337草稿。

0

我想說明一些其他答案沒有結束的事情;是?.push_back(move(?))會比你的情況下慢(?.push_back(?)),因爲移動構造函數需要零\設置移動的對象,這有效地寫了\複製兩個對象。

+0

移動構造函數不需要對移動的對象執行任何操作。除非移動了需要重置爲空的指針,否則它不需要任何東西。 (編譯器生成的移動構造函數不會覆蓋源對象。) – cdhowie 2017-09-12 13:54:51