6

以下のコードでエラーが発生します。

use of deleted function ‘constexpr B::B(const B&)’

これは、移動コンストラクターを指定することによってコピー コンストラクターが (意図的に) 暗黙的に削除され、ベクトルをコピーすると (削除された) コピー コンストラクターが呼び出されるために発生することがわかりました。ベクトルのコピーコンストラクターと代入演算子が使用される理由も理解できたと思います。ただし、移動コンストラクターと代入演算子を使用したいのは明らかです。オブジェクトを移動すると、オブジェクトに含まれるベクトルも移動します。では、移動コンストラクター/代入演算子でベクターの移動コンストラクター/代入演算子を使用するにはどうすればよいでしょうか?

コードは次のとおりです。

#include <vector>

class B {
private:
    /* something I don't want to copy */
public:
    B() {};
    B(B&& orig) {/* move contents */};
    B& operator=(B&& rhs) {
        /* move contents */
        return *this;
    };
};

class A {
private:
    vector<B> vec;
public:
    A() : vec() {};
    A(A&& orig) : vec(orig.vec) {};
    A& operator=(A&& rhs) {
        vec = rhs.vec;
        return *this;
    };
};
4

3 に答える 3

5

「移動」コンストラクターと代入演算子が確実に呼び出されるようにするには、正しい値のカテゴリのオブジェクトを提供する必要があります。値カテゴリは、使用できる演算子とコンストラクターを決定するために使用されます。

値カテゴリ(この場合は左辺値) を xvalue (移動元の右辺値)std::moveに変更するために使用します。

// ...
A(A&& orig) : vec(std::move(orig.vec)) {};
A& operator=(A&& rhs) {
    vec = std::move(rhs.vec);
    return *this;
};

moveオブジェクトをコピーしたり変更したりすることは決してありません。これは単に引数の型の右辺値参照へのキャストであるため、値カテゴリが変更されます。

于 2016-02-12T09:32:01.793 に答える
2

クラスのすべてのメンバーが正しく定義された移動コンストラクター/代入演算子を持つクラスのオブジェクトである場合は、クラスにデフォルトの移動コンストラクター/代入演算子を使用することをお勧めします。これにより、はるかに簡単になり、エラーが発生しにくくなり、クラス メンバーのムーブ コンストラクター/代入演算子の呼び出しが保証されます。

あなたの特定の例では、次のようになります。

class A
{
private:
    vector<B> vec;
public:
    A() : vec() {};
    A(A&&) = default;
    A& operator=(A&&) = default;
};
于 2016-02-12T10:31:49.027 に答える