2013-12-12 19 views
1

如果您做的東西拷貝一個類來存儲,是這樣的:由價值考慮v是否應將自動副本移動到成員中或保持獨立?

struct S { 
    S(std::vector<int> v); 
private: 
    std::vector<int> m; // gonna store v in here 
}; 

我聽說你應該讓編譯器進行復制你,因爲它可以有時更有效地做到這一點。但是,在構造函數的成員初始化列表中,是否應該用vstd::move(v)初始化m?如果v的類型是移動類型,該怎麼辦? (在後一種情況下,我假設你必須使用move。)

+2

平均有一個過載的最佳方法是按值重新移動。 [這個答案](http://stackoverflow.com/questions/15600499/how-to-pass-parameters-correctly/15600615#15600615)討論它。 – chris

+0

如果您按值獲取參數,則您已擁有一份副本。所以沒有必要再複製它(就像'm(v)'會做的那樣)。 'm(std :: move(v))'並不意味着移動,但是如果可能的話它會移動。 – dyp

+0

@DyP但事情是,如果你按價值進行論證,你可能沒有副本,對吧?它可能會被刪除或移動?我想知道是否同樣的事情適用於初始化成員。 – uk4321

回答

1

如果它是僅移動的,那麼最好的方法是按值取值,然後移動。

當v的類型可以是可複製或可移動的時,我將「最佳實踐」的狀態描述爲有點流暢,目前有不同的思想流派。但是,我認爲,這正被接受爲編寫最佳移動感知構造函數的方式,如您所需。

我會說,做你在這裏做了什麼,是的使用移動投射從右值初始化成員。

當您使用構造函數時,請嘗試利用copy-elision。例如,這個:

struct S { 
    S(std::vector<int> v) : m(std::move(v)) {} 
private: 
    std::vector<int> m; 
}; 

std::vector<int> create_vector() 
{ 
    std::vector<int> vec = // initialisation stuff 

    return vec; 
} 

int main() 
{ 
    S instance_of_s{create_vector()}; 
    return 0; 
} 

......理想情況下,由於各種複製精度,理論上應該不復制任何東西。但是,當然,這是編譯器的依賴。

下面是一個演示這個的例子。

#include <iostream> 
#include <memory> 
#include <vector> 

using namespace std; 

class VectorWrapper 
{ 
public: 
    VectorWrapper() : vec(){} 

    VectorWrapper(const VectorWrapper& other) : vec(other.vec){ cout << "COPY" << endl; } 

    VectorWrapper(VectorWrapper&& other) : vec(move(other.vec)){ cout << "MOVE" << endl; } 

private: 
    vector<int> vec; 
}; 

struct S 
{ 
    S(VectorWrapper v) : m(move(v)) {} 
private: 
    VectorWrapper m; 
}; 

int main() 
{ 
    S instance_of_s{VectorWrapper()}; 
    return 0; 
} 

在GCC 4.7.2輸出爲:

MOVE

參考文獻:

http://cpptruths.blogspot.co.uk/2012/03/rvalue-references-in-constructor-when.html

http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

(請注意,這是一系列文章,我錯過了以此開始的鏈接!)