La mia comprensione è che in C ++ 11, quando si restituisce una variabile locale da una funzione in base al valore, al compilatore è consentito trattare quella variabile come riferimento di valore r e 'spostarla' dalla funzione per restituirla (se RVO / NRVO non accade invece, ovviamente).
La mia domanda è: non è possibile interrompere 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;
}
Pensavo che sarebbe stato possibile per un distruttore di un oggetto locale fare riferimento all'oggetto che viene implicitamente spostato, e quindi inaspettatamente vedere un oggetto "vuoto". Ho provato a testare questo (vedi http://ideone.com/ZURoeT ), ma ho ottenuto il risultato 'corretto', senza l'esplicita std::move
in foobar()
. Immagino che ciò sia dovuto a NRVO, ma non ho provato a riorganizzare il codice per disabilitarlo.
Sono corretto in quanto questa trasformazione (causando uno spostamento dalla funzione) avviene implicitamente e potrebbe violare il codice esistente?
AGGIORNAMENTO Ecco un esempio che illustra di cosa sto parlando. I seguenti due collegamenti sono per lo stesso codice. http://ideone.com/4GFIRu - C ++ 03 http://ideone.com/FcL2Xj - C ++ 11
Se guardi l'output, è diverso.
Quindi, suppongo che questa domanda diventi adesso, è stata presa in considerazione quando si è aggiunta la mossa implicita allo standard, ed è stato deciso che era giusto aggiungere questa modifica di rottura poiché questo tipo di codice è abbastanza raro? Mi chiedo anche se qualche compilatore avvertirà in casi come questo ...