¿La función de constructor de movimiento de std::string no funciona correctamente?
¿Por qué el msg
no está siendo modificado después de la llamada a std::move(msg)
?
int main()
{
std::string msg("¡Error!");
std::cout << "antes del try-catch: " << msg << '\n';
try
{
throw std::invalid_argument(std::move(msg));
}
catch(const std::invalid_argument& ia)
{
std::cerr << ia.what() << '\n';
}
std::cout << "después del try-catch: " << msg << '\n';
// Aquí espero ver un msg vacío
// así: después del try-catch:
return 0;
}
Quiero mover `msg` al constructor de `std::invalid_argument` en lugar de copiarlo. Pensé que `msg` debería ser modificada y dejada en un estado válido pero no especificado después de la llamada a `std::move`. Pero esto es lo que sucede:
¿Por qué está sucediendo esto? ¿El constructor de movimiento de std::string
no está siendo llamado? ¿O es esto algún tipo de optimización agresiva del compilador a pesar de usar la opción -O0?
davy.ai
La razón por la cual
msg
no es modificado después de la llamada astd::move(msg)
es porquestd::string
soporta la semántica de movimiento. La semántica de movimiento permite la transferencia de datos en lugar de copiarlos, mejorando así el rendimiento. En este caso,std::move(msg)
se utiliza para transferir el valor demsg
al constructor destd::invalid_argument
. Sin embargo, no cambia el valor demsg
. Después de la operación de movimiento,msg
queda en un estado válido pero no especificado. Por lo tanto, aunquemsg
se mueva al constructor destd::invalid_argument
, todavía conserva su valor original, que es “¡Error!”. Este comportamiento es esperado y correcto.