¿Cuál es la diferencia entre el operador de asignación y el constructor de copias?

105

No entiendo la diferencia entre el constructor de asignaciones y el constructor de copias en C ++. Es así:

class A {
public:
    A() {
        cout << "A::A()" << endl;
    }
};

// The copy constructor
A a = b;

// The assignment constructor
A c;
c = a;

// Is it right?

Quiero saber cómo asignar la memoria del constructor de asignaciones y copiar el constructor.

Alan.chen
fuente

Respuestas:

160

Un constructor de copia se usa para inicializar un objeto previamente no inicializado a partir de los datos de algún otro objeto.

A(const A& rhs) : data_(rhs.data_) {}

Por ejemplo:

A aa;
A a = aa;  //copy constructor

Un operador de asignación se utiliza para reemplazar los datos de un objeto previamente inicializado con los datos de algún otro objeto.

A& operator=(const A& rhs) {data_ = rhs.data_; return *this;}

Por ejemplo:

A aa;
A a;
a = aa;  // assignment operator

Podría reemplazar la construcción de la copia por la construcción predeterminada más la asignación, pero eso sería menos eficiente.

(Como nota al margen: Mis implementaciones anteriores son exactamente las que el compilador le otorga de forma gratuita, por lo que no tendría mucho sentido implementarlas manualmente. Si tiene una de estas dos, es probable que esté administrando manualmente algún recurso. En ese caso, según la regla de tres , es muy probable que también necesite el otro más un destructor).

sbi
fuente
4
Solo una nota: hoy en día (C ++ 11 en adelante), se pueden predeterminar explícitamente con =default;.
Deduplicador
2
@Deduplicator También es importante mencionar que, cuando se adhiere a clasificaciones que requieren constructores triviales, debe hacerlo = default donde se necesita un ctor predeterminado: simplemente implementar un cuerpo vacío por nosotros mismos todavía cuenta como un ctor definido por el usuario y, por lo tanto (en un nivel Standardese ) no es trivial y descalifica al tipo de las clasificaciones que requieren un ctor trivial.
underscore_d
@sbi ¿Puedo decir que en caso de que no se use el constructor de copia y en su lugar se use el operador de asignación, el objeto se crea primero llamando al constructor con argumentos o sin argumentos y luego se usa el operador de asignación y se asignan nuevos valores basados ​​en RHS. En caso de que se use el constructor de copia, se llamará al mismo constructor, pero los valores usados ​​para la inicialización son de otro objeto.
Rajesh
@Rajesh: Estoy confundido acerca de lo que preguntas, y mi sensación es que se debe a que tú también estás confundido. :)¿Intentarás explicar de nuevo de qué estás hablando?
sbi
1
@ CătălinaSîrbu: Podrías. Son dos funciones independientes.
sbi
41

La diferencia entre el constructor de copia y el operador de asignación causa mucha confusión para los programadores nuevos, pero en realidad no es tan difícil. Resumiendo:

  • Si se debe crear un nuevo objeto antes de que se pueda realizar la copia, se utiliza el constructor de copia.
  • Si no es necesario crear un nuevo objeto antes de que se pueda realizar la copia, se utiliza el operador de asignación.

Ejemplo de operador de asignación:

Base obj1(5); //calls Base class constructor
Base obj2; //calls Base class default constructor
obj2 = obj1; //calls assignment operator

Ejemplo de constructor de copias:

Base obj1(5);
Base obj2 = obj1; //calls copy constructor
Arun
fuente
¿Sería justo decir que un operador de asignación combina efectivamente la destrucción de un objeto antiguo con la creación de uno nuevo, pero con las condiciones de que (1) si uno de los pasos en la destrucción del objeto antiguo fuera deshecho por uno de los pasos en la construcción del nuevo, ambos pasos pueden omitirse; (2) los operadores de asignación no deberían hacer cosas malas si un objeto se asigna a sí mismo.
supercat
¿por qué hacer vector <A> v3y luego v3 = v2 (dónde v2está un elemento previamente declarado y que contiene vector<A>) llama al Aconstructor de copia explícito en lugar del operator=? Esperaba operator=que me llamaran en lugar de copy constructorporque mi v3objeto ya estaba declarado en el momento en que hice la tarea
Cătălina Sîrbu
19

La primera es la inicialización de la copia, la segunda es solo la asignación. No existe el constructor de asignaciones.

A aa=bb;

usa el constructor de copia generado por el compilador.

A cc;
cc=aa;

usa el constructor predeterminado para construir cc, y luego el * operador de asignación ** ( operator =) en un objeto ya existente.

¿Quiero saber cómo asignar la memoria del constructor de asignaciones y copiar el constructor?

IDK lo que quiere decir con asignar memoria en este caso, pero si quiere ver qué sucede, puede:

class A
{
public :
    A(){ cout<<"default constructor"<<endl;};
    A(const A& other){ cout<<"copy constructor"<<endl;};
    A& operator = (const A& other){cout <<"assignment operator"<<endl;}
};

También te recomiendo que eches un vistazo a:

¿Por qué se llama al constructor de copia en lugar del constructor de conversión?

¿Qué es la regla de tres?

Luchian Grigore
fuente
5

En pocas palabras

Se llama al constructor de copia cuando se crea un nuevo objeto a partir de un objeto existente, como una copia del objeto existente. Y se llama al operador de asignación cuando a un objeto ya inicializado se le asigna un nuevo valor de otro objeto existente.

Ejemplo-

t2 = t1;  // calls assignment operator, same as "t2.operator=(t1);"
Test t3 = t1;  // calls copy constructor, same as "Test t3(t1);"
Satish
fuente
4

Lo que @Luchian Grigore Said se implementa así

class A
{
public :
    int a;
    A(){ cout<<"default constructor"<<endl;};
    A(const A& other){ cout<<"copy constructor"<<endl;};
    A& operator = (const A& other){cout <<"assignment operator"<<endl;}
};

void main()
{
    A sampleObj; //Calls default constructor
    sampleObj.a = 10;

    A copyConsObj  = sampleObj; //Initializing calls copy constructor

    A assignOpObj; //Calls default constrcutor
    assignOpObj = sampleObj; //Object Created before so it calls assignment operator
}

SALIDA


Constructor predeterminado


constructor de copias


Constructor predeterminado


operador de asignación


Mak
fuente
4

la diferencia entre un constructor de copia y un constructor de asignación es:

  1. En el caso de un constructor de copia, crea un nuevo objeto. ( <classname> <o1>=<o2>)
  2. En el caso de un constructor de asignaciones, no creará ningún objeto, significa que se aplicará a los objetos ya creados ( <o1>=<o2>).

Y las funcionalidades básicas en ambos son las mismas, copiarán los datos de o2 a o1 miembro por miembro.

Nitesh Kumar
fuente
2

Quiero agregar un punto más sobre este tema. "La función de operador del operador de asignación debe escribirse solo como una función miembro de la clase". No podemos hacerlo como una función amiga a diferencia de otros operadores binarios o unarios.

MD BELAL RASHID
fuente
1

Algo que agregar sobre el constructor de copias:

  • Al pasar un objeto por valor, usará el constructor de copia

  • Cuando se devuelve un objeto de una función por valor, usará el constructor de copia

  • Al inicializar un objeto usando los valores de otro objeto (como el ejemplo que da).

Frank Shen
fuente