1. ホーム
  2. c++

[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する

2022-01-23 12:32:23

質問内容

このスニペットは Visual Studio 2013 (Version 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 (Version 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に同梱されているコンパイラは、Copy Constructorを生成して、それをマークしていると思います。 =delete というエラー C2280 が発生します(ちなみに msdn.microsoft.com でドキュメントを見つけることができません)。

さて、Visual Studio 2013ではコンパイル可能(コンパイラが自動生成したコードに依存しているので動作する)だが、Visual Studio 2015ではC2280のためにコンパイルできないコードベースがあるとすると、この問題を解決するにはどうすればよいでしょうか。

私は、クラス A というように

class A
{
public:
   A(){}
   A(A &&){}
   A(const A&)=default;
};

ということです。

解決方法は?

class.copy]/7より、強調は私です。

<ブロッククオート

クラス定義でコピーコンストラクタを明示的に宣言していない場合、明示的でないものが暗黙的に宣言されます。 クラス定義で移動コンストラクタまたは移動代入演算子を宣言している場合、暗黙のうちに宣言されたコピー演算子は、そのクラスで使用されます。 コンストラクタはdeletedとして定義されます。 そうでない場合はdefaultedとして定義されます(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;

また、移動代入演算子も宣言する必要があります。もし本当にこれらの特殊な関数が必要なら、おそらくデストラクタも必要になるでしょう。参照 5つのルール .