Qualcosa mi dà fastidio su:
MyClass& operator=(const MyClass& other)
{
MyClass tmp(other);
swap(tmp);
return *this;
}
In primo luogo, la lettura della parola "swap" quando la mia mente sta pensando "copia" irrita il mio senso comune. Inoltre, metto in dubbio l'obiettivo di questo trucco elegante. Sì, qualsiasi eccezione nella costruzione delle nuove risorse (copiate) dovrebbe avvenire prima dello scambio, il che sembra un modo sicuro per assicurarsi che tutti i nuovi dati vengano riempiti prima di renderli disponibili.
Questo va bene. Quindi, che dire delle eccezioni che si verificano dopo lo scambio? (quando le vecchie risorse vengono distrutte quando l'oggetto temporaneo esce dall'ambito) Dal punto di vista dell'utente del compito, l'operazione è fallita, tranne che non lo ha fatto. Ha un enorme effetto collaterale: la copia è effettivamente avvenuta. Era solo un po 'di pulizia delle risorse che non funzionava. Lo stato dell'oggetto di destinazione è stato modificato anche se l'operazione sembra non riuscita.
Quindi, propongo invece di "swap" per fare un "trasferimento" più naturale:
MyClass& operator=(const MyClass& other)
{
MyClass tmp(other);
transfer(tmp);
return *this;
}
C'è ancora la costruzione dell'oggetto temporanea, ma il prossimo intervento immediato è quello di liberare tutte le risorse attuali del la destinazione prima di spostarsi (e NULLing in modo che non vengano liberati in modo doppio) le risorse della sorgente.
Invece di {costruire, spostare, distruggere}, propongo {costruisci, distruggi, muovi}. La mossa, che è l'azione più pericolosa, è quella presa l'ultima volta dopo che tutto il resto è stato risolto.
Sì, l'errore di distruzione è un problema in entrambi gli schemi. I dati sono corrotti (copiati quando non pensavi che fosse) o persi (liberati quando non pensavi che fosse). Lost è meglio che danneggiato. Nessun dato è migliore dei dati cattivi.
Trasferimento invece di scambio. Questo è il mio suggerimento comunque.
"... hanno praticamente lo stesso codice ..."? Hmm ... Devi fare qualcosa di sbagliato. Cerca di minimizzare la necessità di utilizzare funzioni definite dall'utente per questo e lascia che il compilatore faccia tutto il lavoro sporco. Questo spesso significa incapsulare risorse nel proprio oggetto membro. Potresti mostrarci un codice. Forse abbiamo alcuni buoni consigli sul design. – sellibitze
Possibile duplicato di [Riduzione della duplicazione del codice tra operator = e il costruttore di copie] (http://stackoverflow.com/questions/1477145/reducing-code-duplication-between-operator-and-the-copy-constructor) – mpromonet