Meu entendimento é que no C ++ 11, quando você retorna uma variável local de uma função por valor, o compilador pode tratar essa variável como uma referência de valor r e 'movê-la para fora da função para retorná-la (se O RVO / NRVO não acontece, é claro).
Minha pergunta é: isso não pode quebrar o código existente?
Considere o seguinte 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;
}
Eu pensava que seria possível para um destruidor de um objeto local fazer referência ao objeto que é implicitamente movido e, portanto, inesperadamente ver um objeto 'vazio'. Eu tentei testar isso (ver http://ideone.com/ZURoeT ), mas eu tenho o resultado 'correta' sem a explícita std::move
no foobar()
. Suponho que isso se deva ao NRVO, mas não tentei reorganizar o código para desativá-lo.
Estou certo de que essa transformação (causando uma saída da função) ocorre implicitamente e pode quebrar o código existente?
ATUALIZAÇÃO Aqui está um exemplo que ilustra o que estou falando. Os dois links a seguir são para o mesmo código. http://ideone.com/4GFIRu - C ++ 03 http://ideone.com/FcL2Xj - C ++ 11
Se você olhar para a saída, é diferente.
Então, acho que agora essa pergunta se torna: foi considerada ao adicionar uma mudança implícita ao padrão e foi decidido que não havia problema em adicionar essa alteração, pois esse tipo de código é raro o suficiente? Gostaria também de saber se algum compilador irá avisar em casos como este ...