La mia comprensione è che in C ++ 11, quando si restituisce una variabile locale da una funzione in base al valore, il compilatore può trattare quella variabile come riferimento di valore r e "spostarla" fuori dalla funzione per tornare (se RVO / NRVO non succede invece, ovviamente).
La mia domanda è, non può rompere il codice esistente?
Considera il seguente codice:
#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;
}
I miei pensieri erano che sarebbe stato possibile per un distruttore di un oggetto locale fare riferimento all'oggetto che viene spostato implicitamente e, quindi, vedere inaspettatamente un oggetto "vuoto". Ho provato a testarlo (vedi link ), ma ho ottenuto il risultato "corretto" senza l'esplicito std::move
in foobar()
. Suppongo che sia dovuto a NRVO, ma non ho provato a riorganizzare il codice per disattivarlo.
Sono corretto nel senso che questa trasformazione (causando un movimento fuori dalla funzione) avvenga implicitamente e potrebbe rompere il codice esistente?
Aggiorna Ecco un esempio che illustra ciò di cui sto parlando. I seguenti due link sono per lo stesso codice. link - C ++ 03 link - C ++ 11
Se guardi l'output, è diverso.
Quindi, immagino che questa domanda diventi ora, è stata presa in considerazione quando si è aggiunta la mossa implicita allo standard, e si è deciso che era OK aggiungere questo cambio di rottura in quanto questo tipo di codice è abbastanza raro? Mi chiedo anche se eventuali compilatori avviseranno in casi come questo ...