web-dev-qa-db-ja.com

intのコピーvs std :: move

  • その例のデフォルトのコピーとstd :: moveの違いは何ですか?
  • moveの後に、オブジェクトは新しいものと古いものの間に依存関係がありますか?
int main () {

    int a = 100;
    std::cout<<&a<<std::endl;

    auto a_copy = a;                 // deduced as int
    std::cout<<&a_copy<<std::endl;

    auto a_move = std::move(a);      // deduced as int
    std::cout<<&a_move<<std::endl;

};

出力:

0x7fffffffe094
0x7fffffffe098
0x7fffffffe09c
26
Person.Junkie

thisの例では、違いはありません。最終的には、値が100の3つのintsになります。ただし、タイプによっては間違いなく違いがある可能性があります。たとえば、vector<int>のようなものを考えてみましょう:

std::vector<int> a = {1, 2, 3, 4, 5}; // a has size 5
auto a_copy = a;                      // copy a. now we have two vectors of size 5
auto a_move = std::move(a);           // *move* a into a_move

最後の変数a_moveは、aの内部ポインターの所有権を取得します。つまり、a_moveはサイズ5のベクトルですが、aは空になっています。 movecopyよりもはるかに効率的です(代わりに1000文字列のベクトルである場合を想像してください。a_copyは1000文字列バッファの割り当てと1000文字列のコピーを含みますが、 a_moveは、いくつかのポインタを割り当てるだけです)。

他のいくつかのタイプでは、1つが無効である可能性があります。

std::unique_ptr<int> a{new int 42};
auto a_copy = a;            // error
auto a_move = std::move(a); // OK, now a_move owns 42, but a points to nothing

ただし、多くのタイプで違いはありません。

std::array<int, 100> a;
auto a_copy = a;            // copy 100 ints
auto a_move = std::move(a); // also copy 100 ints, no special move ctor

より一般的には:

T a;
auto a_copy = a;            // calls T(const T& ), the copy constructor
auto a_move = std::move(a); // calls T(T&& ), the move constructor
25
Barry

std::moveを使用すると、左辺値がx値に変更されるだけなので、移動コンストラクターおよび移動代入演算子で使用できます。これらは組み込み型には存在しないため、この例ではmoveを使用しても違いはありません。

11
Drunix

その例のデフォルトのコピーとstd :: moveの違いは何ですか?

違いはありません。何かをコピーすると、移動の要件が満たされます。組み込み型の場合、移動はコピーとして実装されます。

オブジェクトを移動した後、新旧の間に依存関係があります

いいえ、依存関係はありません。両方の変数は独立しています。

6
juanchopanza

他の投稿者の答えを拡張するために、次の例のように、MOVE IS A COPYパラダイムは、PODタイプで構成される(またはPODタイプで構成される他のタイプで構成される)すべてのデータ構造にも適用されます。

_struct Foo
{
    int values[100];
    bool flagA;
    bool flagB;
};

struct Bar
{
    Foo foo1;
    Foo foo2;
};

int main()
{
    Foo f;
    Foo fCopy = std::move(f);
    Bar b;
    Bar bCopy = std::move(b);
    return 0;
}
_

FooBarの両方の場合、どちらも最終的にはPODタイプの集合体であるため、データを別のデータに移動する意味のある方法はありません。それらのデータは間接的に所有されません(を指すまたは他のメモリを参照します)。したがって、これらの場合、移動はコピーとして実装され、元の(fb)は、std::move()行の割り当て後も変更されないままです。

移動セマンティクスは、動的に割り当てられたメモリまたは一意のリソースでのみ意味のある方法で実装できます。

3
mbgda