Sommario
Non eliminare i membri mossa.
Assumendo che il compilatore è completamente C++ 11 conforme, quindi eliminando in modo esplicito il costruttore mossa sarà anche implicitamente dichiarare quanto segue:
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
cioè se si dichiara un costruttore spostare (o move assignment operator), e non dichiarare membri di copia, sono implicitamente dichiarati come cancellati. Così il vostro Foo classe completo è come se:
class Foo
{
public:
Foo(int i) : i_(i) {}
Foo(Foo&&) = delete;
Foo(const Foo&) = delete; // implicitly declared
Foo& operator=(const Foo&) = delete; // implicitly declared
int i_;
};
Ora vector<Foo>::push_back(Foo(1))
richiede che Foo
essere MoveConstructible
. MoveConstructible
potrebbe essere soddisfatto da un costruttore di movimento accessibile o anche da un costruttore di copia accessibile. Ma Foo
non ha né. Per risolvere il problema è possibile:
class Foo
{
public:
Foo(int i) : i_(i) {}
Foo(const Foo&) = default;
Foo& operator=(const Foo&) = default;
int i_;
};
I.e. imposta i membri di copia predefiniti e rimuove il membro di spostamento eliminato.
In generale non è una buona idea eliminare esplicitamente i membri del movimento. Se si desidera che una classe sia copiabile ma non "mobile", dichiarare esattamente come si farebbe in C++ 03: dichiarare/definire i membri della copia. Puoi lasciare che i membri della copia siano generati dal compilatore con = default
e che contino ancora come una dichiarazione utente. E non dichiarare membri del movimento. Sposta i membri che non esistono non sono gli stessi membri del movimento eliminato.
I membri di spostamento eliminati indicano che non è possibile costruire una copia di Foo
da un valore di rvalore, anche se il costruttore di copia avrebbe funzionato correttamente. Questo è raramente l'intento desiderato.
Anche se si desidera che la classe non sia copiabile o mobile, è meglio eliminare solo i membri della copia e lasciare i membri spostati non dichiarati (ovvero non esistono). Se riesci a rivedere il codice (incluso il tuo), e vedere i membri delle mosse eliminate, sono quasi sicuramente errati o al meglio superflui e confusi.
Un giorno qualcuno troverà un buon caso d'uso per i membri del movimento cancellati. Ma sarà un caso d'uso raro. Se si vede un tale modello nel codice, si dovrebbe aspettare il codice autore per avere una spiegazione molto buona. In caso contrario, è probabile che i membri di movimento eliminati siano semplicemente errati (nel migliore dei casi superflui). Ma il lato positivo questo errore si mostrerà al momento della compilazione, invece che in fase di esecuzione (come nel tuo esempio).
Ecco un grafico di sintesi di ciò che il compilatore implicitamente fare quando si dichiara in modo esplicito qualsiasi dei membri speciali. Quei quadrati colorati rosso rappresentano un comportamento disapprovato.
= default
e = delete
contano come dall'utente dichiarato.
Click here se si desidera visualizzare l'intero piano di scorrimento.
Perché push_back richiede che il tipo sia MoveInsertable. Basta leggere i documenti: http://en.cppreference.com/w/cpp/container/vector/push_back –