2

次の点を考慮してください。

class Example : boost::noncopyable
{
    HANDLE hExample;
public:
    Example()
    {
        hExample = InitializeHandle();
    }
    ~Example()
    {
        if (hExample == INVALID_HANDLE_VALUE)
        {
            return;
        }
        FreeHandle(hExample);
    }
    Example(Example && other)
        : hExample(other.hExample)
    {
        other.hExample = INVALID_HANDLE_VALUE;
    }
    Example& operator=(Example &&other)
    {
        std::swap(hExample, other.hExample); //?
        return *this;
    }
};

ここでの私の考えでは、デストラクタはまもなく「その他」で実行されるため、スワップを使用して移動代入演算子でデストラクタ ロジックを再度実装する必要はありません。しかし、それが合理的な仮定であるかどうかはわかりません。これは「大丈夫」でしょうか?

4

3 に答える 3

8

次のことを想像してください。

// global variables
Example foo;

struct bar {
    void f() {
        x = std::move(foo); // the old x will now live forever
    }
    Example x;
}

同様のイディオムであるコピー アンド スワップ(この場合はムーブ アンド スワップ) を使用すると、デストラクタがすぐに実行されるようになります。

Example& operator=(Example other) // other will be moved here
{
    std::swap(hExample, other.hExample);
    return *this;
} // and destroyed here, after swapping
于 2012-03-17T02:37:16.210 に答える
5

それは問題ないはずですが、推奨される pass-by-value の手法よりも優れていることはほとんどありません。この場合、この状況では move コンストラクターが使用されます。

于 2012-03-17T02:37:38.937 に答える
3

ここでの私の考えは、デストラクタはまもなく「その他」で実行されるということです

それならあなたの考えは間違っています。const 以外のアクセス権を持つ任意のオブジェクトから移動できます。そして、オブジェクトはこの後も無期限に生き続けることができます。

現在のデータを古いオブジェクトに入れることは技術的に正しいです。しかし、それは良い考えではありません。スタック変数を使用することをお勧めします。

Example& operator=(Example &&other)
{
    Example temp(std::move(other));  //other is now empty.
    std::swap(hExample, temp);       //our stuff is in `temp`, and will be destroyed
    return *thisl
}

または、(Visual Studio を使用していない場合) 移動を正しくサポートするラッパーにデータを格納し、コンパイラによって生成された移動コンストラクターにジョブを実行させます。

于 2012-03-17T02:36:02.360 に答える