Si. Hay dos opciones comunes. Uno, que generalmente no se recomienda, es llamar operator=
explícitamente desde el constructor de copia:
MyClass(const MyClass& other)
{
operator=(other);
}
Sin embargo, proporcionar un bien operator=
es un desafío cuando se trata de lidiar con el estado anterior y los problemas que surgen de la autoasignación. Además, todos los miembros y bases se inicializan por defecto primero, incluso si se les va a asignar desde other
. Esto puede que ni siquiera sea válido para todos los miembros y bases e incluso cuando es válido es semánticamente redundante y puede resultar prácticamente caro.
Una solución cada vez más popular es implementar operator=
utilizando el constructor de copia y un método de intercambio.
MyClass& operator=(const MyClass& other)
{
MyClass tmp(other);
swap(tmp);
return *this;
}
o incluso:
MyClass& operator=(MyClass other)
{
swap(other);
return *this;
}
Una swap
función suele ser sencilla de escribir, ya que simplemente intercambia la propiedad de los componentes internos y no tiene que limpiar el estado existente ni asignar nuevos recursos.
Las ventajas del lenguaje de copiar e intercambiar es que es automáticamente seguro para la autoasignación y, siempre que la operación de intercambio sea sin tirar, también es muy seguro para excepciones.
Para estar fuertemente seguro de excepciones, un operador de asignación escrita 'a mano' generalmente tiene que asignar una copia de los nuevos recursos antes de desasignar los recursos antiguos del cesionario, de modo que si ocurre una excepción al asignar los nuevos recursos, el estado anterior aún se puede volver a . Todo esto viene gratis con copiar e intercambiar, pero generalmente es más complejo y, por lo tanto, propenso a errores, para hacerlo desde cero.
Lo único que debe tener cuidado es asegurarse de que el método de intercambio sea un intercambio verdadero, y no el predeterminado std::swap
que usa el constructor de copia y el operador de asignación en sí.
Normalmente swap
se utiliza un miembro . std::swap
funciona y está garantizado 'no-throw' con todos los tipos básicos y tipos de puntero. La mayoría de los punteros inteligentes también se pueden intercambiar con una garantía de no tirar.