2012-01-24 9 views
16

Ho appena trascorso una quantità eccessiva di tempo a trafficare con un errore di complilazione in Visual Studio. Ho distillato il codice nel piccolo esempio compilabile di seguito e provato su IdeOne e ho ottenuto lo stesso errore che è possibile vedere here.Perché questo codice tenta di chiamare il costruttore di copie?

Mi chiedo il motivo per cui il seguente codice tenta di chiamare B(const B&) invece di 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; 
} 

io non indicava esplicitamente alcun costruttore, in modo B(std::move(binst)) dovrebbe chiamare il compilatore ha generato B(B&&), no?

Quando cambio B a

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

Si compila bene. Perchè è questo?

Sarà estremamente sconveniente se questo non può essere risolto dalla classe base perché ho una classe template che usa il posizionamento new e sposta i costruttori come nell'esempio, e richiederà ogni classe che non è copiabile (che è non e sicuramente non dovrebbe essere un requisito per l'uso con la mia classe template) per avere un costruttore di move esplicitamente definito.

+0

C'è un compilatore generato B (B &&)? Il mio C++ 11 è ancora un po 'arrugginito. E il tuo B (B &&) ha bisogno di inizializzare A (A &&)? – CashCow

+0

@CashCow si, tutto ciò che fa è spostare ogni membro (se questo è sbagliato allora ti sto guardando, Kerrek SB ':)') –

+0

Compila bene su GCC 4.6, GCC 4.7 e Clang 3.0. –

risposta

15

Se si utilizza Visual Studio 2010 o 2012, essere informati: il compilatore non non generare automaticamente i costruttori mossa per voi. Questo non è stato implementato. Quindi devi scriverli da solo.

+1

Va notato che i dettagli su quando un costruttore di mosse dovrebbe essere implicitamente definito come predefinito sono cambiati verso la fine del processo di standardizzazione e vc2010 è stato usato prima. Inoltre, vc2010 non supporta '= delete', il che rende difficile parlare della conformità dei costruttori di spostamenti :) – avakar

+0

Ciò è seriamente fastidioso. Desidero ardentemente VS11. Grazie. –

+4

@Seth Carnegie: VC11 non genererà automaticamente il costruttore di movimento ... http: //blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx "I riferimenti di riepilogo v3.0 aggiungono nuove regole per generare automaticamente i costruttori di mosse e spostare gli operatori di assegnazione in determinate condizioni.Questo non sarà implementato in VC11, che continuerà per seguire il comportamento di VC10 di generazione automatica dei costruttori di movimenti/spostamento degli operatori di assegnazione. " –

5

È necessario essere di fronte a un bug del compilatore. Lo standard dice che B ottiene un costruttore di mosse implicitamente dichiarato e definito; tutte le condizioni di 12.8 (9) sono soddisfatte (ad esempio, B non ha un costruttore di copie esplicitamente dichiarato, l'assegnazione della copia, ecc. e il costruttore di movimento non sarebbe implicitamente dichiarato deleted).

+1

Immagino che questo sia ciò che ottengo usando VS, un compilatore che è stato scritto tra standard. Grazie. –

Problemi correlati