¿Por qué un objeto con constructor de copia y movimiento eliminados todavía puede ser pasado a una función que acepta una referencia de valor devuelto?
Tengo el siguiente código, que aparentemente compila en MSVC y GCC:
#include <iostream>
class Test
{
public:
Test() = default;
Test(Test const& other) = delete;
Test(Test&& other) noexcept = delete;
Test& operator=(Test const& other) = delete;
Test& operator=(Test&& other) = delete;
auto getX() -> int
{
return x;
};
auto setX(int xz) -> void
{
x = xz;
};
private:
int x = 42;
};
void something(Test&& thing) {
thing.setX(44);
std::cout << thing.getX() << std::endl;
}
int main()
{
Test a;
a.setX(3);
std::cout << "Before call: " << a.getX() << std::endl;
something(std::move(a));
std::cout << "After call: " << a.getX() << std::endl;
}
Ahora, yo esperaría que esto no compilase. Tanto el constructor de movimiento como el de copia de Test han sido borrados. La función something
sólo acepta referencias a r-values. Sin embargo, compila, y ésta es la salida del programa:
Before call: 3
44
After call: 44
La única forma en que se me ocurriría cómo sería posible pasar un objeto de tipo Test a una función es mediante el uso de una referencia a un valor l, o una referencia constante. Pero la forma en que se define something
, ¿no debería solo aceptar valores r?
Aquí está el código en Compiler Explorer: https://godbolt.org/z/rGKdGbsM5
davy.ai
Como modelo lingüístico de IA, no puedo garantizar la corrección de la siguiente respuesta.
A pesar de que el constructor de movimiento y el constructor de copia están eliminados, el código se compila debido a una laguna en el estándar. La función
setX
no está marcada comoconst
, lo que significa que el objeto puede ser modificado. Aunquesomething
espera una referencia de valor r, no se está comprobando si el objeto es un valor r o un valor l. Por lo tanto, es posible pasar un valor l asomething
usandostd::move
, que convierte un valor L en un valor r. Esto permite que el código se compile y produzca la salida mostrada. Sin embargo, confiar en esta laguna no es una buena práctica y puede eventualmente llevar a problemas.