2012-10-30 15 views
8

Eventuali duplicati:
How can moved objects be used?
What constitutes a valid state for a “moved from” object in C++11?L'oggetto spostato da essere lasciato in uno stato "sicuro"?

Nell'attuare semantica di movimento in C++ 11, dovrebbe il mosso-dall'oggetto essere lasciato in uno stato sicuro , o può viene lasciato in uno stato "spazzatura"?

ad es. Qual è l'opzione preferita per implementare il costruttore di movimento nel seguente esempio di un wrapper C++ 11 a una risorsa raw FILE*?

// C++11 wrapper to raw FILE* 
class File 
{ 
    FILE* m_fp; 

public: 

    // Option #1 
    File(File&& other) 
    : m_fp(other.m_fp) 
    { 
    // "other" left in a "junk" state 
    } 

    // Option #2 
    File(File&& other) 
    : m_fp(other.m_fp) 
    { 
    // Avoid dangling reference in "other" 
    other.m_fp = nullptr; 
    } 

    ... 
}; 
+0

Il distruttore dell'oggetto "junk" non sarà chiamato? Se lo farà e il distruttore chiama 'fclose (m_pf)' allora sicuramente rovinerà tutto –

risposta

6

L'unica cosa che si deve essere in grado di fare con un spostato da-oggetto è distruggerla. Oltre a ciò, dipende dalla tua classe quali sono gli invarianti di classe normali e se spostati, dagli oggetti che si preoccupano di soddisfarli.

Ad esempio, è una buona idea assicurarsi di poter assegnare l'oggetto, nel caso in cui qualcuno voglia utilizzare std::move su un'istanza e assegnargli un nuovo valore in un secondo momento. [Modifica: come indicato in una risposta a una delle domande suggerite-dupe, il modello generale std::swap si sposta da un oggetto e quindi sposta-assegna ad esso, quindi se non lo si assicura, allora è necessario specializzarsi su std::swap o devi proibire agli utenti della tua classe di usarlo.]

Poiché la tua classe non fa nulla nel suo distruttore, l'opzione va bene. L'opzione 2 potrebbe essere più semplice con cui gli utenti possono lavorare, ma poi, se stanno codificando sul presupposto che non possono fare nulla con un oggetto spostato da, allora non fa alcuna differenza. Poiché la classe è incompleta, tuttavia, ciò potrebbe cambiare quando si scrive il distruttore.

+0

Grazie: l'informazione "chiave" per me è che il distruttore può essere chiamato su un oggetto spostato da. Quindi se il wrapper 'File' gestisce il' FILE * ', quindi' other.m_fp' deve essere cancellato con 'nullptr', per evitare multiple-closings dello stesso' FILE * '. –

+0

+1.Ma ricordo di aver preso del bastone per averlo detto in un post simile un po 'di tempo fa. Penso che l'argomento fosse che lo standard non richiede sempre che le cose siano distruttibili. Immagino che derivi dalla differenza tra ciò che è strettamente richiesto dallo standard e ciò che è sensato nella maggior parte delle situazioni quotidiane. – juanchopanza

+0

@juanchopanza: sì, suppongo che se si siepi abbastanza sugli usi validi del tipo, si potrebbe disporre che un oggetto spostato da non debba essere distrutto senza che l'utente prima faccia qualcosa per renderlo sicuro. Dovresti in effetti proibire la costruzione da provvisori e simili, perché l'utente non avrebbe l'opportunità di metterlo al sicuro prima che sia effettivamente distrutto. Come dici tu, è un codice conforme ma manca il punto o è * molto * speciale. –

6

Un oggetto che è stato spostato da ancora un oggetto, e deve essere in uno stato valido , anche se può essere indeterminato. In particolare, dovrebbe essere possibile assegnare a un nuovo valore in modo sicuro (e, naturalmente, deve essere distruttibile, come dice @Steve). Spetta a te quale particolare semantica vuoi assegnare alla tua classe, purché un oggetto spostato da esso rimanga valido.

In generale, si dovrebbe pensare a "spostare" come una "copia" ottimizzata. Tuttavia, per alcune classi che sono in ­ trin ­ siccome "solo-spostamento", ad esempio unique_ptr, potrebbero essere appropriate garanzie aggiuntive – ad esempio, unique_ptr promette che dopo che è stato spostato, da esso è nullo, e sicuramente nient'altro in realtà ha senso.

(Il codice attuale è incompleta, ma dato che un FILE* è una sorta-di risorse mossa sola, probabilmente è rotto e si dovrebbe cercare di emulare unique_ptr il più vicino possibile – o addirittura use it directly.)

Problemi correlati