Rozumiem, że w C ++ 11, gdy zwracasz zmienną lokalną z funkcji według wartości, kompilator może traktować tę zmienną jako odwołanie do wartości r i „przenosić” ją z funkcji, aby ją zwrócić (jeśli Oczywiście RVO / NRVO się nie zdarza).
Moje pytanie brzmi: czy to nie może złamać istniejącego kodu?
Rozważ następujący kod:
#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;
}
Myślałem, że możliwe byłoby, aby destruktor obiektu lokalnego odwoływał się do obiektu, który zostaje niejawnie poruszony, a zatem nieoczekiwanie zobaczyłby „pusty” obiekt. Próbowałem to sprawdzić (patrz http://ideone.com/ZURoeT ), ale mam „prawidłowy” wynik bez wyraźnej std::move
in foobar()
. Zgaduję, że było to spowodowane NRVO, ale nie próbowałem zmienić kodu, aby to wyłączyć.
Czy mam rację, że ta transformacja (powodująca wyjście z funkcji) zachodzi niejawnie i może uszkodzić istniejący kod?
AKTUALIZACJA Oto przykład, który ilustruje to, o czym mówię. Poniższe dwa łącza dotyczą tego samego kodu. http://ideone.com/4GFIRu - C ++ 03 http://ideone.com/FcL2Xj - C ++ 11
Jeśli spojrzysz na wynik, jest inny.
Sądzę więc, że to pytanie się teraz stało, czy zostało to wzięte pod uwagę przy dodawaniu niejawnego przeniesienia do standardu, i zdecydowano, że dodanie tej przełomowej zmiany jest w porządku, ponieważ ten rodzaj kodu jest dość rzadki? Zastanawiam się także, czy jakieś kompilatory będą ostrzegać w takich przypadkach ...