Ho una classe che richiede un costruttore di copia e un operatore di assegnazione non predefinito (contiene elenchi di puntatori). Esiste un modo generale per ridurre la duplicazione del codice tra il costruttore di copie e l'operatore di assegnazione?Riduzione della duplicazione del codice tra operator = e il costruttore di copie
risposta
Non c'è "via generale" per la scrittura di costruttori di copia personalizzati e operatori di assegnazione che funziona in tutti i casi. Ma c'è un idioma chiamato "dalla duplicazione & -swap":
class myclass
{
...
public:
myclass(myclass const&);
void swap(myclass & with);
myclass& operator=(myclass copy) {
this->swap(copy);
return *this;
}
...
};
E 'utile in molti (ma non tutti) le situazioni. A volte puoi fare di meglio. Un vettore o una stringa potrebbe avere un incarico migliore che riutilizza la memoria allocata se fosse abbastanza grande.
+1 - riassunto buono e conciso di copy-swap penso. Buona idea anche sul riutilizzo dello spazio di archiviazione. –
Si potrebbe voler indicare la sottigliezza qui tra il proprio operatore = e il più costante const myclass & operator = (const myclass & other); – Bill
Lo swap() dovrebbe probabilmente essere contrassegnato come notro. Idem sul commento di Bills. Qualche altra esplosione sarebbe carina. –
Calcolare il codice comune per una funzione membro privata. Un semplice (piuttosto artificiosa) Esempio:
#include <iostream>
class Test
{
public:
Test(const char* n)
{
name = new char[20];
strcpy(name, n);
}
~Test()
{
delete[] name;
}
// Copy constructor
Test(const Test& t)
{
std::cout << "In copy constructor.\n";
MakeDeepCopy(t);
}
// Assignment operator
const Test& operator=(const Test& t)
{
std::cout << "In assignment operator.\n";
MakeDeepCopy(t);
}
const char* get_name() const { return name; }
private:
// Common function where the actual copying happens.
void MakeDeepCopy(const Test& t)
{
strcpy(name, t.name);
}
private:
char* name;
};
int
main()
{
Test t("vijay");
Test t2(t); // Calls copy constructor.
Test t3("");
t3 = t2; // Calls the assignment operator.
std::cout << t.get_name() << ", " << t2.get_name() << ", " << t3.get_name() << '\n';
return 0;
}
+1: questo è quasi sempre il modo migliore per gestire la duplicazione del codice all'interno di una classe. –
perdita di memoria! MakeDeepCopy ignora la possibilità del nome che punta già alla memoria allocata. – sellibitze
Ma è un peccato che il costruttore di copie non possa usare gli inizializzatori dei membri, in questo modo ... – xtofl
My &My::operator = (My temp) // thanks, sellibitze
{
swap (*this, temp);
return *this;
}
e implementare uno specialista std::swap<> (My &, My &)
.
Questo è il modo in cui dovrebbe apparire copy - & - swap. Stai creando esplicitamente una copia che altrimenti potrebbe essere eliminata. C'è un grande articolo a riguardo qui: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ – sellibitze
Come nota Dave, alexandrescu ha già scoperto circa 6 anni fa: http : //www.ddj.com/cpp/184403855. Interessante anche leggere! –
errm, per inciso il poster è anche chiamato Dave. Mi dispiace per la confusione - intendevo Dave Abrahams di cpp-next :) –
Come già sottolineato da alcuni manifesti, avere operatore = creare un nuovo oggetto con il costruttore di copia e quindi utilizzare lo swap è la tecnica comune utilizzata per non dover replicare il codice in operator =.
Detto questo, voglio sottolineare un pro e un contro di questa tecnica per aiutarti a decidere se è appropriato.
Pro - eccezione sicurezza
Se l'oggetto non ha i requisiti delle risorse che potrebbero causare un tiro e assumendo che di swap non buttare, questa tecnica fornisce la forte garanzia di sicurezza rispetto alle eccezioni (sia l'oggetto che viene assegnato a ha assunto il valore dell'altro oggetto o è invariato).
Con - risorsa impronta
Un problema con questa tecnica è che richiede un nuovo oggetto completo deve essere creato prima di quello vecchio viene rilasciato. Se il tuo oggetto richiede molte risorse, questo può essere un problema.
penso che dovresti essere in grado di chiamare il costruttore di copie all'interno dell'operatore = –
Alcune risposte sono qui: http://stackoverflow.com/questions/1457842/is-this-good-code-copy-ctor-operator –