2012-01-24 13 views
16

Acabo de pasar una cantidad desordenada de tiempo jugando con un error de compilación en Visual Studio. He destilado el código en el pequeño ejemplo compilable a continuación y lo probé en IdeOne y obtuve el mismo error que puede ver en here.¿Por qué este código intenta llamar al constructor de copia?

Me pregunto por qué el siguiente código intenta llamar B(const B&) en lugar de B(B&&):

#include <iostream> 

using namespace std; 

class A { 
public: 
    A() : data(53) { } 
    A(A&& dying) : data(dying.data) { dying.data = 0; } 

    int data; 

private: 
    // not implemented, this is a noncopyable class 
    A(const A&); 
    A& operator=(const A&); 
}; 

class B : public A { }; 

int main() { 
    B binst; 

    char* buf = new char[sizeof(B)]; 

    B* bptr = new (buf) B(std::move(binst)); 

    cout << bptr->data << endl; 

    delete[] buf; 
} 

que no definió explícitamente ningún constructor, por lo B(std::move(binst)) debe llamar al compilador genera B(B&&), ¿no?

cuando cambio B a

class B : public A { 
public: 
    B() { } 
    B(B&&) { } 
}; 

Se compila bien. ¿Por qué es esto?

Será extremadamente inconveniente si esto no se puede solucionar desde la clase base porque tengo una clase de plantilla que usa colocación nueva y mueve constructores como el ejemplo, y se requerirá que cada clase no se pueda copiar (que es no y definitivamente no debería ser un requisito para su uso con mi clase de plantilla) tener un constructor de movimiento definido explícitamente.

+0

¿Hay un compilador generado B (B &&)? Mi C++ 11 todavía está un poco oxidado. ¿Y tu B (B &&) necesitaría inicializar A (A y A)? – CashCow

+0

@CashCow sí, todo lo que hace es mover cada miembro (si eso está mal, entonces te estoy mirando, Kerrek SB ':)') –

+0

Compila bien en GCC 4.6, GCC 4.7 y Clang 3.0. –

Respuesta

15

Si está usando Visual Studio 2010 o 2012, tenga en cuenta: el compilador no no generará automáticamente constructores de movimiento para usted. Eso no fue implementado. Entonces necesitas escribirlos tú mismo.

+1

Debe tenerse en cuenta que los detalles de cuándo un constructor de movimiento debe definirse implícitamente como predeterminado han cambiado casi al final del proceso de estandarización y vc2010 ya existía antes. Además, vc2010 no admite '= delete', lo que dificulta hablar sobre la conformidad de los constructores de movimientos :) – avakar

+0

Eso es realmente molesto. Anhelo VS11. Gracias. –

+4

@Seth Carnegie: VC11 no generará automáticamente mover el constructor tampoco ... http: //blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx "Rvalue references v3.0 agrega nuevas reglas para generar automáticamente constructores de movimiento y mover operadores de asignación bajo ciertas condiciones. Esto no se implementará en VC11, que continuará seguir el comportamiento de VC10 de nunca generar automáticamente constructores de movimiento/operadores de asignación de movimiento ". –

5

Debe enfrentar un error en el compilador. El estándar dice que B obtiene un constructor de movimiento definido y definido implícitamente; se cumplen todas las condiciones de 12.8 (9) (es decir, B no tiene un constructor de copia explícitamente declarado, una copia-asignación, etc., y el constructor de movimiento no se declararía implícitamente deleted).

+1

Supongo que esto es lo que obtengo al usar VS, un compilador que se escribió entre estándares. Gracias. –

Cuestiones relacionadas