1

コンパイラのスプラッシュ画面は次のとおりです (バージョンなど)。

C:\Program Files\Microsoft Visual Studio 10.0\VC>cl.exe
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

usage: cl [ option... ] filename... [ /link linkoption... ]

私は基本クラス(テンプレートです)を持っています。それは次のとおりです。

template <typename T>
class Base {

    public:

        Base<T> & operator = (const Base<T> &);
        Base<T> & operator = (Base<T> &&);

};

私は、決して再実装しない派生クラスを持っていoperator =ます。

私が次のことをした場合:

Derived<int> derived;
derived=Derived<int>();

operator =左辺値を受け入れる は 2 行目で呼び出されます。

の定義に入りDerived<T>、次を追加すると:

template <typename T>
Derived<T> & Derived<T>::operator = (Derived<T> && other) {

    Base<T>::operator=(static_cast<Base<T> &&>(other));

    return *this;

}

operator =右辺値を受け入れる が呼び出されます。

operator =左辺値を取る を (ほぼ同じ方法で)実装しても、この動作は持続します。

より良い言い回しがない場合: 何を与えるか?

私は C++ を誤解していますか、それとも本来の動作方法ではないのでしょうか?

4

4 に答える 4

2

概要: VS がより完全な C++11 サポートで更新されるまで、必要な移動代入演算子を手動で定義する必要があります。


コピーまたは移動代入演算子を宣言しないため、コンパイラが暗黙的にそれらを宣言および定義する場合があります。次に、これらのデフォルトの実装は、基本クラスのコピーおよび移動代入演算子を使用して、基本クラスのサブオブジェクトをコピーまたは移動します。

ただし、移動代入演算子の暗黙的な宣言は、クラスにユーザー宣言のコピー-ctor、移動-ctor、コピー-代入演算子、または dtor がある場合など、多くの状況で抑制されます。クラスにそれらのいずれかがある場合、移動代入演算子を自動的に取得することはできません。[編集:そして Alexandre C. は、VS2010 は移動代入演算子または ctor を暗黙的に宣言することは決してないと指摘しています。]

移動代入演算子がないderived=Derived<int>();と、暗黙的に宣言/定義されたコピー代入演算子が呼び出されます。これは、 のコピー代入演算子を呼び出しますが、Base<T>呼び出さBase<T>::operator = (Base<T> &&)れません。

移動代入演算子のデフォルトの定義が必要な場合でも、その暗黙の宣言を抑制することの 1 つを行う必要がある場合は、新しい= default構文を使用できます (ただし、標準には欠陥があり、場合によって= defaultは' t 実際にはデフォルトの定義を取得しますが、解決されています)、ただし VS10 はサポートしていません= default。VS がより完全な C++11 サポートで更新されるまで、必要な移動代入演算子を手動で定義する必要があります。

C++11 が完全にサポートされているので、暗黙の宣言に依存しないのは良い考えだと思います。また、暗黙的に宣言できる特別なメンバー関数は、常に明示的に宣言する必要があります (= delete作成したくないかのように)。暗黙的な宣言は、もともと C との下位互換性のために行われました。明示的な宣言は理解しやすく、C++11 が追加した現在、欠点はありません= default

于 2012-07-04T20:29:43.350 に答える
1

この場合、ユーザー宣言のコピー操作、移動操作、またはユーザー宣言のデストラクタがない Base<int>限り、移動コンストラクタを呼び出す必要があります。基本クラスのサブオブジェクトを含む基本クラスのサブオブジェクトを移動する、暗黙的に宣言された移動代入演算子があります。Derived<T>Derived<T>Base<T>

ただし、Visual C++ (Visual C++ 2012 RC 以降) は暗黙的に移動操作を生成しないため、移動ではなくコピーが実行されることがわかります。移動可能な型を集約または派生させ、集約型または派生型を移動可能にする場合は、独自のムーブ コンストラクターとムーブ代入演算子を定義する必要があります。

移動操作の仕様とそれらが暗黙的に宣言される状況は、過去 2 年間の標準化の間に数回変更されました。移動操作の暗黙的な宣言が C++11 に追加されたのは 2010 年 2 月になってからです (つまり、Visual C++ 2010 の完成後に変更されました)。その後、昨年 C++11 が完成するまでに仕様が何度か変更され、かなり論争の的になった.

Visual C++ 2012 は、暗黙的に移動操作も生成しません。

于 2012-07-04T20:59:21.600 に答える
1

MSVC は、暗黙的な移動の構築/代入を生成しませんhttp://msdn.microsoft.com/en-us/library/dd293668.aspxを参照してください。

その理由は、暗黙的な移動のセマンティクスが標準の作成中に多くの変更を受けており、MSVC10 が終了した時点では最終的なコンセンサスが得られていなかったためです。

結論: 手動で使用するすべてのムーブ コンストラクター/ムーブ代入演算子を明示的に宣言する必要があります。= defaultあなたを助ける修飾子はありません。これは、多くのswapメンバー関数を作成するか、1) 本当に必要な場合 (コピー不可のクラス)、または 2) コードをプロファイリングしてコピーを削除する必要がない限り、move セマンティクスを放棄することを意味します。

デフォルトのコピー割り当ては暗黙的に生成され、これがここで得られるものです。

于 2012-07-04T20:52:34.720 に答える
1

標準 (3337、12.8.24)。標準
Base::operator =; を使用して入力すると、Base::operator =(Base&&) が使用されます。

于 2012-07-04T19:52:04.883 に答える