2017-10-01 5 views
3

私はstd::vector C ::ベクトル

よう
struct Mystruct 
{ 
    Mystruct(const std::vector<int>& w): v(w) 
    { 
    std::cout << "Copy constructor :" << v.at(0) << "\n"; 
    } 
    Mystruct(const std::vector<int>&& w): v(w) 
    { 
    std::cout << "Move Constructor :" << v.at(0) << "\n"; 
    } 
    private: 
    std::vector<int> v; 
}; 

を保持するクラスを持っていると私は

int main() 
{ 
    auto x = std::vector<int> {1,2,3}; 
    Mystruct M1(x); 
    Mystruct M2(std::vector<int> {3,2,1}); 
    return 0; 
} 

M1のようなオブジェクトを作成し、コピーコンストラクタを使用して構築されており、 M2 "move"コンストラクタを使用していますが、両方の割り当てがvとwの異なるアドレスを保持していますが、2番目のコンストラクタの初期化リストでv(std :: move(w))を使用すると同じことが起こります。私は両方の割り当てがwの内容をコピーしていると思います、これは正しいですか?その場合は、コピーする代わりにwの内容を移動するにはどうすればいいですか?

+2

"移動"部分はオブジェクトではなく*リソース*を参照します。 – Rakete1111

+3

アドレス 'v.data()'を見てください。 –

答えて

7

まず、オブジェクトを移動してもアドレスは変更されません。定義上、オブジェクトのアドレスを変更することはできません。アドレスはオブジェクトの定義の一部なので、オブジェクトのアドレスを変更することはできません。別の住所がある場合は、別のオブジェクトがあります。どのような移動(少なくとも標準ライブラリのクラスに関して)は、オブジェクトの動的に割り当てられたリソースの所有権を譲渡することです。

第2に、あなたは何も移動していません。移動するには、移動コンストラクタを呼び出さなければなりません。つまり、r値を渡す必要があります。名前付きオブジェクトは決してr値ではありません。したがって、r値参照があっても、それでもstd::moveでキャストする必要があります。しかし、あなたのケースでは、それでさえ十分ではありません。標準ライブラリでは、すべての移動コンストラクタの署名がType(Type&&)であり、決してType(const Type&&)ではありません。 const値を渡すと、std::moveでキャストしても、移動コンストラクタではなくコピーコンストラクタが呼び出されます。移動コンストラクタを呼び出すには、オブジェクトをconstにすることはできません。

だから、ベクトル*を移動し、あなたのコンストラクタは次のようになります。

Mystruct(std::vector<int>&& w): v(std::move(w)) 
{ 
    std::cout << "Move Constructor :" << v.at(0) << "\n"; 
} 

そして、それが実際に移動されたかどうかを確認するためのアドレスを比較するために、あなたはvのアドレスを比較すべきではないとし、 w(それらは変更されず、変更することもできません)が、v.data()w.data()は、ベクトルの動的に割り当てられたリソースを指しています。

*移動コンストラクタではありません。移動コンストラクタは、署名を持つでしょうMystruct(Mystruct&&)またはMystruct(const Mystruct&&)