2016-01-09 24 views
2

在下面的代碼中,我期望從不調用A的複製構造函數,因爲項目應該直接在emplace_back的向量上創建,然後總結果應該是返回值優化。將一個項目追加到一個向量複製所有以前的項目

這似乎是這樣。但是,每次追加到矢量時,由於調用emplace_back,所有以前的項目都將被複制。這是爲什麼發生?

#include <iostream> 
#include <vector> 
#include <string> 

using namespace std; 


static int _id = 0; 

class A{ 
public: 
    A(): name(_id++){ 
     cout << "Created" << this->name << endl; 
    } 

    A(const A& other): name(other.name){ 
     cout << "Copied" << this->name << endl; 
    } 

    A(const A&& other): name(other.name){ 
     cout << "Moved" << this->name << endl; 
    } 

    ~A(){ 
     cout << "Deleted"<< this->name <<endl; 
    } 

private: 
    int name; 
}; 


vector<A> f2(){ 
    cout << "Entering f2" << endl; 
    auto ret = vector<A>(); 
    for (int i = 0; i < 3; i++){ 
     //auto obj = A(); 
     cout << "Adding obj" << endl; 
     ret.emplace_back(); 
     cout << "Added obj" << endl; 
    } 
    cout << "Returning" << endl; 
    return ret; 
} 

int main() 
{ 
    { 
     auto c = f2(); 
     cout << "Exiting stack" << endl; 
    } 
    return 0; 
} 

我用gcc 4.8.4編譯它使用任何的:

gcc main.cpp -std=c++11 
gcc main.cpp -std=c++11 -O3 

輸出是:

Entering f2 
Adding obj 
Created0 
Added obj 
Adding obj 
Created1 
Copied0 
Deleted0 
Added obj 
Adding obj 
Created2 
Copied0 
Copied1 
Deleted0 
Deleted1 
Added obj 
Returning 
Exiting stack 
Deleted0 
Deleted1 
Deleted2 

而且我預計不會有副本,喜歡的東西:

Entering f2 
Adding obj 
Created0 
Added obj 
Adding obj 
Created1 
Added obj 
Adding obj 
Created2 
Added obj 
Returning 
Exiting stack 
Deleted0 
Deleted1 
Deleted2 

改變emplace_backpush_back不能解決這個問題,並增加了額外的舉措。

+0

的可能的複製[當矢量長如何執行移動語義?](http://stackoverflow.com/questions/8001823/how-to-enforce-move-semantics-when- a-vector-grow) – LogicStuff

回答

4

當它運行的存儲空間向量將重新分配其內存塊,而舊對象複製到他們的新的地方。你可以通過調用vector.reserve(<expected number of items>);
另外值得一提的是,矢量擔保分期常量push_back複雜顯著減少這種重新分配的數量。這意味着,隨着您不斷添加商品,重新分配的次數會越來越少,因此通常不會擔心。

或者,如果你只是需要某種容器,不需要它在內存中連續分配,考慮使用不同的容器。像std::deque

3

另外,如果你標記您的移動構造函數noexcept,那麼當向量的增長,它會移動,而不是複製。

又見How to enforce move semantics when a vector grows?

+0

Upvoted,但也讓OP知道他的移動構造函數上的簽名是毫無價值的(放下'const')。 –

相關問題