8

std::vector を含む単純なクラスがあり、クラスを値で返すときに (RVO ではなく)移動セマンティクスを利用したいと考えています。

移動コンストラクター、コピー コンストラクター、およびコピー代入演算子を次のように実装しました。

class A
{
    public:
        // MOVE-constructor.
        A(A&& other) :
            data(std::move(other.data))
        {
        }

        // COPY-constructor.
        A(const A& other) :
            data(other.data)
        {
        }

        // COPY-ASSIGNMENT operator.
        A& operator= (const A& other);
        {
            if(this != &other)
            {
                data = other.data;
            }

            return *this;
        }

    private:
        std::vector<int> data;
};

上記の実装は正しいですか?

そして別の質問: これらのメンバーのいずれかを実装する必要がありますか、それともコンパイラによって自動生成されますか? コピー コンストラクターとコピー代入演算子が既定で生成されることはわかっていますが、コンパイラはムーブ コンストラクターも自動生成できますか? (このコードは、MSVC と GCC の両方でコンパイルします。)

ご提案いただきありがとうございます。(すでに同様の質問がいくつかあることは知っていますが、この正確なシナリオではありません。)

4

2 に答える 2

6

これらはすべて、このクラス [*] では不要です。これらのいずれも宣言しないと、暗黙的なものになるからです。

あなたのコンストラクタは問題ありません。したがって、次のコードは表向きは move コンストラクターを呼び出します。

A f() { return A(); }
A a = f(); // move construct (not copy construct) from the return value of f

実際には、move-elision が作動する可能性があり、その場合、引数なしのコンストラクターのみが実際に呼び出されます。コピーと移動以外のコンストラクターを提供する予定があると思います;-)

あなたのコピー割り当ては問題ありません。暗黙のものとは異なりますが、暗黙のものにはない自己割り当てチェックがあるという点だけです。自己割り当てチェックに価値があるかどうかについて議論する必要はないと思いますが、それは間違いではありません。

移動代入演算子が定義されていません。他のものを定義したことを考えると、そうする必要がありましたが、残りを取り除くと暗黙的です[*]。移動代入演算子 (ユーザー定義または暗黙的) は、次のコードがコピーではなく移動することを保証するものです。

A a;
a = f();

[*] 完成した C++11 実装で、これまでのところ存在しません。この機能がまだ実装されているかどうかは、コンパイラごとに確認できます。おそらく、#defineMSVC が実装されるまでは、恐ろしい悪ふざけが発生することになるでしょう。

于 2013-01-08T11:22:18.903 に答える
2

この正確なシナリオでは、移動/コピー/代入関数を宣言する必要はありません。コンパイラは正しいデフォルトを生成します。

于 2013-01-08T10:16:18.150 に答える