¿Por qué no se llama al constructor de movimiento?
Tengo el siguiente fragmento de código:
“`c++
#include <iostream>
struct T {
int a;
<pre><code>T() = default;
T(T& other) {
std::cout << "copy &\n";
}
T(T&& other) {
std::cout << "move &&\n";
}
</code></pre>
};
void foo(T&& x) {
T y(x); // ¿Por qué se llama al constructor de copia?
}
int main() {
T x;
foo(std::move(x));
<pre><code>return 0;
</code></pre>
}
“`
No entiendo por qué se prefiere el constructor de copia en lugar del constructor de movimiento, a pesar de que foo()
acepta una referencia de valor de rvalue.
davy.ai
La razón por la cual se llama al constructor de copia en este código es que el parámetro pasado a
foo()
es una expresión lvalue (x
). Aunquefoo()
acepta una referencia de valor temporal (rvalue-reference), una lvalue también puede unirse a ella.En este caso, cuando
std::move(x)
se pasa como argumento afoo()
, simplemente conviertex
en una expresión de valor temporal (rvalue) y la pasa a la función. Dentro defoo()
, la expresiónT y(x)
crea un objeto nuevoy
y lo inicializa usando el constructor de copia, ya quex
es una referencia lvalue aT
.Para forzar que se llame al constructor de movimiento en su lugar, debe cambiar la firma de
foo()
para tomar una referencia lvalue (T& x
), o convertirx
a una referencia de valor temporal dentro defoo()
utilizandostd::move()
:c++
void foo(T&& x) {
T y(std::move(x)); // se llama al constructor de movimiento
}