6

次のコードをコンパイルしようとすると、コンパイラエラーC2248が発生します

#include <list>
#include <memory>
using namespace std;


class data
{
public:

    static data parse()
    {
        data d;
        data::parse(d);
        return d;
    }

    list<std::unique_ptr<data>> l;

private:

    static void parse(data& node)
    {       }
};


int main()
{

    return 0;
}

なんで?どうすればこれを修正できますか?

注:のstd::shared_ptr代わりに使用しても問題ありませんstd::unique_ptr

4

3 に答える 3

10

タイプに応じて移動操作を提供する必要があります。

data(data&& other)
    : l(std::move(other.l))
{
}

data& operator=(data&& other)
{
    l = std::move(other.l);
    return *this;
}

また、ユーザーが宣言したコンストラクターを追加したので、ユーザーが宣言したデフォルトのコンストラクターも必要になります。

data() { }

私の理解では、最終的なC ++ 11言語標準に従って、コードはそのまま正しいものです。Visual C ++は、移動操作が暗黙的に生成される場合の最終仕様を完全には実装していません(Visual C ++ 2012 RC以降)。暗黙的な移動操作が生成されるタイミングの仕様は、標準化プロセスの非常に遅い段階で数回変更されました。

移動可能であるがコピー不可能なデータメンバーを持つクラスタイプがある場合C、Visual C ++は暗黙的な移動コンストラクターまたは移動代入演算子を生成せず、暗黙的なコピーコンストラクターとコピー代入演算子は両方ともmove-の存在によって抑制されます。データメンバーのみ。つまり、集約移動専用タイプが必要な場合は、集約クラスの移動操作を自分で提供する必要があります。

(少なくとも、これはコンパイラーでの実験からの私の理解です。)

于 2012-07-03T20:20:31.597 に答える
5

まず最初に、VC ++はまだムーブコンストラクターとムーブ代入演算子を自動的に生成しません。つまり、それらを自分で定義する必要があります。

次に、ローカル変数を返す場合、コンパイラは、実際にそれらをコピーする通常のルートに進む前に、最初にローカル変数を移動しようとします。ただし、そのためには、movectorが必要です。それがないため、通常のコピーを試行し、生成されたコピーctorを介して、コピーコンストラクターを自動的に呼び出します。コピーコンストラクターはstd::list、その要素タイプのコピーctorを呼び出しようとします。このstd::unique_ptr場合、プライベートです。

適切なmovectorまたはのcopyctorを呼び出さないcopyctorを定義する必要がありますstd::unique_ptr(つまり、コンテンツのディープコピーを作成します)。

于 2012-07-03T20:16:12.623 に答える
2

簡単な答え:(C ++ 11固有)aのアイテムは、listコピー可能または移動可能である必要があります。Aunique_ptrは設計上コピーできませんが、制御されたタイプも移動可能である限り、移動可能です。

data移動セマンティクスを実装しておらず、コンパイラーがそれを実行しなかったため、タイプは移動できません。

unique_ptr移動セマンティクスを実装すると、list:で使用できます。

data(ddata&&) {};

標準によれば、moveコンストラクターはコンパイラーによってクラス用に生成されます。ただし、VS10はこれをサポートしていません。これは、実行中の問題である可能性があります。

詳細については、CR:MoveSemanticsの正規実装に関する私の投稿を参照してください。

于 2012-07-03T20:21:19.100 に答える