Entiendo que en C ++ 11, cuando devuelve una variable local de una función por valor, el compilador puede tratar esa variable como una referencia de valor r y 'moverla' fuera de la función para devolverla (si RVO / NRVO no sucede en su lugar, por supuesto).
Mi pregunta es, ¿no puede esto romper el código existente?
Considere el siguiente código:
#include <iostream>
#include <string>
struct bar
{
bar(const std::string& str) : _str(str) {}
bar(const bar&) = delete;
bar(bar&& other) : _str(std::move(other._str)) {other._str = "Stolen";}
void print() {std::cout << _str << std::endl;}
std::string _str;
};
struct foo
{
foo(bar& b) : _b(b) {}
~foo() {_b.print();}
bar& _b;
};
bar foobar()
{
bar b("Hello, World!");
foo f(b);
return std::move(b);
}
int main()
{
foobar();
return EXIT_SUCCESS;
}
Pensé que sería posible que un destructor de un objeto local haga referencia al objeto que se mueve implícitamente y, por lo tanto, vea inesperadamente un objeto 'vacío'. He intentado poner a prueba esta (ver http://ideone.com/ZURoeT ), pero me dio el resultado 'correcto' sin la explícita std::move
en foobar()
. Supongo que se debió a NRVO, pero no intenté reorganizar el código para deshabilitarlo.
¿Estoy en lo cierto en que esta transformación (que causa un movimiento fuera de la función) ocurre implícitamente y podría romper el código existente?
ACTUALIZACIÓN Aquí hay un ejemplo que ilustra de lo que estoy hablando. Los siguientes dos enlaces son para el mismo código. http://ideone.com/4GFIRu - C ++ 03 http://ideone.com/FcL2Xj - C ++ 11
Si nos fijamos en la salida, es diferente.
Entonces, supongo que esta pregunta ahora es: ¿se consideró esto al agregar un movimiento implícito al estándar, y se decidió que estaba bien agregar este cambio importante ya que este tipo de código es bastante raro? También me pregunto si algún compilador advertirá en casos como este ...