6

現在、割り当てられたメモリへのポインターを含むオブジェクトを使用してセマンティクスを正しく移動する方法を見つけようとしています。実際のストレージへの内部生ポインタを含む大きなデータ構造があります(効率上の理由から)。ここで、移動コンストラクターと move を追加しましたoperator=()。これらのメソッドではstd::move()、新しい構造へのポインタを指定しています。ただし、他の構造体からのポインターをどうするかはわかりません。

これが私がやっていることの簡単な例です:

class big_and_complicated {
   // lots of complicated code
};

class structure {
public:
   structure() :
      m_data( new big_and_complicated() )
   {}

   structure( structure && rhs ) :
      m_data( std::move( rhs.m_data ) )
   {
      // Maybe do something to rhs here?
   }

   ~structure()
   {
      delete m_data;
   }

private:
   big_and_complicated * m_data;
}

int main() {
  structure s1;
  structure s2( std::move( s1 ) );
  return 0;
}

今、私が理解していることstd::move( s1 )からs2、安全に実行できる唯一のことは、s1そのコンストラクターを呼び出すことです。ただし、私が見る限り、これによりs1、デストラクタに含まれるポインタが削除され、s2役に立たなくなります。std::move()したがって、ポインターを ing するときにデストラクタを安全にするために何かをしなければならないと推測しています。ここで行う最も安全な方法は0、移動したオブジェクトでに設定することdeleteです。これまでのところ、この推論は正しいですか? または、std::move()実際にポインターを無効にして、その使用を安全にするのに十分なほどスマートですか? これまでのところ、実際のテスト スイートでクラッシュは見られませんが、move-constructor が実際に呼び出されるかどうかは確認していません。

4

1 に答える 1

18

ポインターを「移動」することは、ポインターをコピーすることと同じであり、移動元の値を null に設定しませ(「移動」は、std::move実際には何も移動せず、引数の値カテゴリを変更するだけなので、ここでは引用符で囲みます)。rhs' ポインターをコピーして、次のように設定するだけnullptrです。

struct structure
{
    structure()
      : m_data{new big_and_complicated{}}
    { }

    structure(structure&& rhs)
      : m_data{rhs.m_data}
    {
        rhs.m_data = nullptr;
    }

    structure& operator =(structure&& rhs)
    {
        if (this != &rhs)
        {
            delete m_data;
            m_data = rhs.m_data;
            rhs.m_data = nullptr;
        }
        return *this;
    }

    ~structure()
    {
        delete m_data;
    }

private:
    big_and_complicated* m_data;

    structure(structure const&) = delete;             // for exposition only
    structure& operator =(structure const&) = delete; // for exposition only
}

std::unique_ptr<big_and_complicated>さらに良いことに、代わりに使用big_and_complicated*すると、これを自分で定義する必要はありません。

#include <memory>

struct structure
{
    structure()
      : m_data{new big_and_complicated{}}
    { }

private:
    std::unique_ptr<big_and_complicated> m_data;
}

最後に、実際にコピー不可のままにしたい場合を除き、structure適切な移動セマンティクスを内部に実装し、オブジェクトを直接保持する方がよいbig_and_complicatedでしょうstructurebig_and_complicated

于 2012-01-26T22:32:00.977 に答える