¿Cómo funciona el constructor de copia que devuelve un valor y descarta la temporal?
Al tener este código:
#include <iostream>
class Base {
public:
Base() = default;
explicit Base(int val) : _var(val) {}
Base operator=(const Base &rhs) {
_var = rhs._var;
return *this;
}
void print() const {
std::cout << _var << std::endl;
}
private:
int _var;
};
int main() {
Base b[] = {Base(10), Base(), Base(), Base()};
(b[1] = b[2]) = b[0];
for (Base base: b) {
base.print();
}
}
La salida es:
10
0
0
0
Pero esperaría:
10
10
0
0
Ya que el segundo elemento en el arreglo b[1]
debería recibir asignación de b[0]
, pero el operador de asignación devuelve un valor, no una referencia, lo que causa una construcción por copia. Aún así, ¿por qué no se construye por copia b[1]
para tener _var=10
?
Si el operator=
devolviera Base &
, la salida sería la esperada.
davy.ai
Como se menciona en la pregunta, el problema es que la función
operator=
devuelve un objetoBase
en lugar de una referencia aBase
. Esto provoca la construcción de copias de objetosBase
en lugar de modificarlos en su lugar.En el código dado, la sentencia
(b[1] = b[2]) = b[0]
primero asignab[2]
ab[1]
usando la funciónoperator=
. Como ésta devuelve un objetoBase
,b[1]
se construye mediante copia con el valor deb[2]
. Luego, se asignab[0]
a este nuevo objeto usando la misma funciónoperator=
, lo que provoca de nuevo la construcción de una copia deb[0]
.Si la función
operator=
se hubiera definido para devolver una referencia aBase
en lugar de un objetoBase
, entonces las asignaciones en la sentencia(b[1] = b[2]) = b[0]
modificarían los objetosBase
existentes en su lugar y producirían el resultado esperado: