Tengo una clase que requiere un constructor de copia no predeterminado y un operador de asignación (contiene listas de punteros). ¿Hay alguna forma general de reducir la duplicación de código entre el constructor de copia y el operador de asignación?Reducción de la duplicación de código entre operator = y el constructor de copia
Respuesta
No hay "de manera general" para la escritura de constructores de copia de encargo y operadores de asignación que funciona en todos los casos. Pero hay un idioma llamado "contra copias & -Swap":
class myclass
{
...
public:
myclass(myclass const&);
void swap(myclass & with);
myclass& operator=(myclass copy) {
this->swap(copy);
return *this;
}
...
};
Es útil en muchos (pero no todas) las situaciones. A veces puedes hacerlo mejor. Un vector o una cadena podría tener una asignación mejor, que reutiliza el almacenamiento asignado si era lo suficientemente grande.
+1 - resumen bueno y concisa del cambio de copia, creo. También es una buena idea reutilizar el almacenamiento. –
Es posible que desee señalar la sutileza aquí entre su operador = y el más estándar const myclass & operator = (const myclass & other); – Bill
El intercambio() probablemente debería marcarse como nothrow. Ídem en el comentario de Bills. Un poco más de explicación sería agradable. –
Factoriza el código común para una función de miembro privado. Un simple (y no artificial) ejemplo:
#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: esta es casi siempre la mejor forma de manejar la duplicación de código dentro de una clase. –
pérdida de memoria! MakeDeepCopy ignora la posibilidad de que el nombre ya esté apuntando a la memoria asignada. – sellibitze
Pero es una pena que el constructor de copias no pueda usar los inicializadores de miembros, de esta manera ... – xtofl
My &My::operator = (My temp) // thanks, sellibitze
{
swap (*this, temp);
return *this;
}
e implementar un std::swap<> (My &, My &)
especializada.
Así es como debe verse copy & & swap. Está creando explícitamente una copia que, de otro modo, podría eludirse. Hay un excelente artículo al respecto aquí: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ – sellibitze
Como Dave notó, alexandrescu ya encontró sobre esto hace 6 años: http : //www.ddj.com/cpp/184403855. Interesante leer también! –
errm, por cierto, el cartel también se llama Dave. Lamento la confusión, me refiero a Dave Abrahams de cpp-next :) –
Como ya se ha señalado en bastantes pósters, tener operator = crear un nuevo objeto con el constructor de copia y luego usar swap es la técnica común utilizada para no tener que replicar el código en operator =.
Dicho esto, quiero señalar algunos pro y contra de esta técnica para ayudarlo a decidir si es apropiado.
Pro - excepción de seguridad
Si el objeto tiene necesidades de recursos que podrían causar un tiro y suponiendo que swap no arrojará, esta técnica proporciona la fuerte garantía de la seguridad de excepción (siendo asignado ya sea el objeto que ha adquirido el valor del otro objeto o no se modifica).
Con - recursos huella
Un problema con esta técnica es que requiere un nuevo objeto completo a crearse antes de liberar la antigua. Si su objeto requiere muchos recursos, esto puede ser un problema.
- 1. ¿Cuál es la diferencia entre sobrecargar operator = y sobrecargar el constructor de copia?
- 2. Conflicto entre el constructor de copia y el constructor de reenvío
- 3. ¿Cuán fanáticamente eliminas la Duplicación de código?
- 4. Eliminar la duplicación de código
- 5. C++ constructor de copia, los temporales y la semántica copia
- 6. constructor o constructor de copia?
- 7. ¿Por qué el constructor de copia implícita llama al constructor de copia de la clase base y el constructor de copia definido no?
- 8. RVO/NRVO y el constructor público de copia no definida
- 9. Cómo escribir el constructor de copia de clase de plantilla
- 10. parámetros de plantilla, #define y la duplicación de código
- 11. ¿Por qué este código intenta llamar al constructor de copia?
- 12. Evitar la duplicación de código en F #
- 13. implícito constructor de copia
- 14. Cómo evitar la duplicación de código
- 15. Duplicación de código y especialización de plantilla (cuando la función especializada tiene diferentes tipos de retorno)
- 16. ¿Cómo puedo evitar la duplicación de código?
- 17. Implementando el constructor de copia en términos de operador =
- 18. subclase de QObject, qRegisterMetaType, y el constructor de copia privada
- 19. invocando el constructor de copia dentro de otro constructor
- 20. Ventanas Duplicación y duplicación de tokens
- 21. constructor de copia con el parámetro ArrayList
- 22. El constructor de copias y el operador de asignación
- 23. Constructor de copia de Matlab
- 24. llamada al constructor de copia
- 25. vector :: push_back insiste en usar el constructor de copia aunque se proporciona un constructor de movimiento
- 26. Ningún constructor de copia disponible o el constructor de copia se declara 'explícito'
- 27. Ternary operator + C++ 11 constructor from initializer_list
- 28. Herencia múltiple sin herencia múltiple y sin duplicación de código
- 29. ¿Cuál es la diferencia entre operator >> y operator >>> en java?
- 30. Deduplicar esta duplicación de código Java
creo que debería poder llamar al constructor de copias dentro del operador = –
Algunas respuestas están aquí: http://stackoverflow.com/questions/1457842/is-this-good-code-copy-ctor-operator –