Error comstackdor C ++ C2280 “intentando hacer referencia a una función eliminada” en Visual Studio 2013 y 2015

Este fragmento se comstack sin errores en Visual Studio 2013 (Versión 12.0.31101.00 Actualización 4)

class A { public: A(){} A(A &&){} }; int main(int, char*) { A a; new A(a); return 0; } 

mientras se comstack con este error en Visual Studio 2015 RC (Versión 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 ========== 

Creo que el comstackdor enviado con Visual Studio 2015 genera Copy Constructor y lo marca como =delete y así obtengo el error C2280 (que, dicho sea de paso, no puedo encontrar documentado en msdn.microsoft.com).

Ahora, digamos que tengo una base de código que es comstackble con Visual Studio 2013 (y funciona porque depende del código generado automáticamente por el comstackdor) pero no comstackble con Visual Studio 2015 debido a C2280, ¿cómo puedo solucionar el problema?

Estaba pensando en declarar la clase A de esta manera:

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

¿Me estoy perdiendo de algo?

De [class.copy] / 7, énfasis mío:

Si la definición de clase no declara explícitamente un constructor de copia, se declara implícitamente una no explícita. Si la definición de clase declara un constructor de movimiento o un operador de asignación de movimiento, el constructor de copia declarado implícitamente se define como eliminado ; de lo contrario, se define como predeterminado (8.4). El último caso está en desuso si la clase tiene un operador de asignación de copia declarado por el usuario o un destructor declarado por el usuario.

Hay una sección equivalente con una redacción similar para la asignación de copias en el párrafo 18. Por lo tanto, su clase es realmente:

 class A { public: // explicit A(){} A(A &&){} // implicit A(const A&) = delete; A& operator=(const A&) = delete; }; 

por eso no puedes copiarlo y construirlo. Si proporciona una asignación / constructor de movimiento y aún desea que la clase se pueda copiar, tendrá que proporcionar explícitamente esas funciones especiales para miembros:

  A(const A&) = default; A& operator=(const A&) = default; 

También necesitarás declarar un operador de asignación de movimiento. Si realmente necesita estas funciones especiales, probablemente también necesite el destructor. Ver la Regla de los Cinco .

Tuve el mismo problema y fue debido a una variable de miembro mal definida:

 double const deltaBase = .001; 

Al colocar esto, se eliminará el constructor de copia. Deshágase de la “const” y asigne en el constructor.

Si escribe un constructor de movimiento definido por el usuario para su clase, se eliminará el constructor de copia. Esto se debe a que si una clase necesita un comportamiento especial para su constructor de movimiento, probablemente necesite un comportamiento similar en su constructor de copia, por lo que el constructor de la copia se eliminará para evitar que use el comportamiento predeterminado inadvertidamente.

Si desea definir su propio constructor de movimiento y usar el constructor de copia predeterminado, debe declararlo como default , como sugirió en su pregunta:

 class A { public: A(){} A(A &&){} //I know what I'm doing, compiler, use the default version. A(const A&)=default; }; 

Tenga en cuenta que si define un constructor de movimiento personalizado, también debe pensar en los operadores de asignación y el destructor.