Compartir a través de


Constructores de copia y operadores de asignación de copia (C++)

Nota:

A partir de C++ 11, se admiten dos tipos de asignación en el lenguaje: asignación de copia y asignación de movimiento. En este artículo, "asignación" significa asignación de copia a menos que se establezca explícitamente lo contrario. Para obtener información sobre la asignación de movimiento, consulte Operadores de constructores de movimiento y asignaciones de movimiento (C++).

Tanto la operación de asignación como la operación de inicialización provocan que los objetos se copien.

  • Asignación: cuando el valor de un objeto se asigna a otro objeto, el primer objeto se copia en el segundo objeto. Por lo tanto, este código copia el valor de b en a:

    Point a, b;
    ...
    a = b;
    
  • Inicialización: la inicialización se produce cuando se declara un nuevo objeto, cuando se pasan argumentos de función por valor o cuando se devuelve por valor de una función.

Puede definir la semántica de “copy” para los objetos de tipo de clase. Por ejemplo, considere este código:

TextFile a, b;
a.Open( "FILE1.DAT" );
b.Open( "FILE2.DAT" );
b = a;

El código anterior podría significar “copiar el contenido de FILE1.DAT en FILE2.DAT” o podría significar “omitir FILE2.DAT y convertir b en un segundo identificador para FILE1.DAT”. Debe adjuntar la semántica de copia adecuada a cada clase, como se muestra a continuación:

  • Use un operador de asignación operator= que devuelva una referencia al tipo de clase y tome un parámetro que se pasa por referencia const; por ejemplo ClassName& operator=(const ClassName& x);.

  • Uso del constructor de copias.

Si no declara un constructor de copias, el compilador genera uno automáticamente miembro a miembro. Del mismo modo, si no declara una asignación de copia, el compilador genera una automáticamente miembro a miembro. Declarar un constructor de copias no suprime el operador de asignación de copias generado por el compilador, ni viceversa. Si implementa cualquiera de ellos, se recomienda que implemente también el otro. Cuando se implementan ambos, el significado del código es claro.

El constructor de copias toma un argumento de tipo ClassName&, donde ClassName es el nombre de la clase. Por ejemplo:

// spec1_copying_class_objects.cpp
class Window
{
public:
    Window( const Window& );            // Declare copy constructor.
    Window& operator=(const Window& x); // Declare copy assignment.
    // ...
};

int main()
{
}

Nota:

Haga que el tipo del argumento del constructor de copias const ClassName& sea siempre que sea posible. Esto evita que el constructor de copias modifique accidentalmente el objeto copiado. También permite copiar objetos const.

Constructores de copias generados por el compilador

Los constructores de copia generados por el compilador, como los constructores de copia definidos por el usuario, tienen un único argumento de tipo "referencia a nombre de clase". Una excepción es cuando todas las clases base y las clases miembro tienen constructores de copia declarados como tomar un único argumento de tipo constclass-name&. En ese caso, el argumento del constructor de copias generado por el compilador también es const.

Cuando el tipo de argumento al constructor de copias no es const, la inicialización que se realiza copiando un objeto const genera un error. Lo contrario no es cierto: si el argumento es const, puede inicializar copiando un objeto que no sea const.

Los operadores de asignación generados por el compilador siguen el mismo patrón para const. Toman un solo argumento de tipo ClassName& a menos que los operadores de asignaciones de todas las clases base y clases de miembro tomen argumentos de tipo const ClassName&. En este caso, el operador de asignación generado para la clase toma un argumento const.

Nota:

Cuando los constructores de copias, generados por el compilador o definidos por el usuario, inicializan las clases base virtuales, estas se inicializan solo una vez: en el momento en que se construyen.

Las implicaciones son similares a las del constructor de copias. Cuando el tipo del argumento no es const, la asignación de un objeto const genera un error. Lo contrario no es cierto: si un valor const se asigna a un valor que no es const, la asignación se realiza correctamente.

Para obtener más información sobre los operadores de asignaciones sobrecargados, vea Asignación.