このスニペットはVisual Studio 2013(バージョン12.0.31101.00 Update 4)でエラーなしでコンパイルされます
class A
{
public:
A(){}
A(A &&){}
};
int main(int, char*)
{
A a;
new A(a);
return 0;
}
visual Studio 2015 RC(バージョン14.0.22823.1 D14REL)ではこのエラーでコンパイルされますが:
1>------ Build started: Project: foo, Configuration: Debug Win32 ------
1> foo.cpp
1>c:\dev\foo\foo.cpp(11): error C2280: 'A::A(const A &)': attempting to reference a deleted function
1> c:\dev\foo\foo.cpp(6): note: compiler has generated 'A::A' here
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Visual Studio 2015に同梱されているコンパイラーがコピーコンストラクターを生成し、=delete
そして、私はエラーC2280を受け取ります(ところで、msdn.Microsoft.comで文書化されたものを見つけることができません)。
今、Visual Studio 2013でコンパイル可能なコードベースがあり(コンパイラによって自動的に生成されたコードに依存しているため機能します)、C2280のためにVisual Studio 2015でコンパイルできないコードベースがあるとしましょう、どうすれば問題を修正できますか?
私はクラスA
を次のように宣言することを考えていました:
class A
{
public:
A(){}
A(A &&){}
A(const A&)=default;
};
私は何かが欠けていますか?
[class.copy]/7から、私の強調:
クラス定義でコピーコンストラクターが明示的に宣言されていない場合、非明示的なコンストラクターが暗黙的に宣言されます。 クラス定義が移動コンストラクターまたは移動代入演算子を宣言する場合、暗黙的に宣言されたコピーコンストラクターは、deleted;それ以外の場合は、デフォルト(8.4)として定義されます。後者のケースは、クラスにユーザーが宣言したコピー割り当て演算子またはユーザーが宣言したデストラクタがある場合は非推奨です。
パラグラフ18には、コピーの割り当てに類似した文言を持つ同等のセクションがあります。したがって、クラスは次のようになります。
class A
{
public:
// explicit
A(){}
A(A &&){}
// implicit
A(const A&) = delete;
A& operator=(const A&) = delete;
};
それがあなたがそれをコピー構築できない理由です。移動コンストラクター/割り当てを提供し、それでもクラスをコピー可能にする場合は、これらの特別なメンバー関数を明示的に提供する必要があります。
A(const A&) = default;
A& operator=(const A&) = default;
また、移動割り当て演算子を宣言する必要があります。これらの特別な機能が本当に必要な場合は、おそらくデストラクタも必要になります。 Rule of Five を参照してください。
私は同じ問題を抱えていましたが、それは不十分に定義されたメンバー変数によるものでした:
double const deltaBase = .001;
これを配置すると、コピーコンストラクターが削除されます。 「const」を取り除き、コンストラクターで割り当てます。
クラスにユーザー定義の移動コンストラクターを記述すると、コピーコンストラクターは削除されます。これは、クラスが移動コンストラクターに特別な動作を必要とする場合、おそらくコピーコンストラクターで同様の動作が必要になるため、コピーコンストラクターが削除されて、既定の動作を誤って使用しないようにするためです。
独自の移動コンストラクターを定義する場合andデフォルトのコピーコンストラクターを使用する場合、質問で提案したように、default
として宣言する必要があります。
class A
{
public:
A(){}
A(A &&){}
//I know what I'm doing, compiler, use the default version.
A(const A&)=default;
};
カスタム移動コンストラクターを定義する場合は、割り当て演算子とデストラクターについても考慮する必要があることに注意してください。
コピーアクターを「デフォルト」にした後でも、このエラーが発生しました。結局、クラスメンバーの1人(rapidjsonのDocumentオブジェクト)がコピーを許可していませんでした。デフォルトのctorの初期化子リストの*(new rapidjson :: Document())で初期化された参照に変更しました。デフォルトのコピーctorに加えて、すべての個々のメンバーもコピー可能にする必要があるようです。