Created attachment 27111 [details] code A different result - just reordering the cout output. #include <iostream> using namespace std; struct X { int value; X() { cout << "default construction" << std::endl; value = 0; } X(const X& other) { cout << "copy construction" << std::endl; value = 1; } X(X&& other) { cout << "move construction" << std::endl; value = 2; } X& operator = (const X& other) { cout << "assignment" << std::endl; value = 3; return *this; } }; X&& f() { X x; return std::move(x); } int main() { cout << "Hello References [1]" << std::endl; X x0 = f(); cout << "x0: " << x0.value << std::endl; X&& x1 = f(); cout << "No copy construction or assignment expected" << std::endl; cout << "x1: " << x1.value << std::endl; cout << "Hello References [2]" << std::endl; X y0 = f(); cout << "y0: " << y0.value << std::endl; X&& y1 = f(); cout << "y1: " << y1.value << std::endl; cout << "No copy construction or assignment expected" << std::endl; return 0; } // Seems g++ 4.6.1 is buggy: // Hello References [1] // default construction // move construction // x0: 2 // default construction // No copy construction or assignment expected // x1: 6295648 // Hello References [2] // default construction // move construction // y0: 2 // default construction // y1: 0 // No copy construction or assignment expected
I don't see what this example is supposed to demonstrate. the two lines X&& x1 = f(); and X&& y1 = f(); produce references to invalid memory, any access to that is undefined behaviour. You cannot impose any reliable constraints on the values such references.
This is just a bug in your program, not G++ (In reply to comment #0) > > X&& f() { > X x; > return std::move(x); > } This function is unsafe, it returns a reference to a local variable. You probably meant it to return X not X&& It is effectively the same as: X& f() { X x; return x; } (except G++ warns about that, because it's simpler) > > int main() { > cout << "Hello References [1]" << std::endl; > X x0 = f(); > cout << "x0: " << x0.value << std::endl; > X&& x1 = f(); This reference is bound to a variable that went out of scope when f() returned. > cout << "No copy construction or assignment expected" << std::endl; > cout << "x1: " << x1.value << std::endl; This accesses deallocated memory. N.B. you don't even need to use std::move, the compiler will automatically select the move constructor to create the return value here: X f() { X x; return x; }
(In reply to comment #2) > > X&& f() { > > X x; > > return std::move(x); > > } > > This function is unsafe, it returns a reference to a local variable. You > probably meant it to return X not X&& > > It is effectively the same as: > > X& f() { > X x; > return x; > } > > (except G++ warns about that, because it's simpler) Maybe this could be taken as a RFE for a warning with std::move? Many people learning C++11 are bound to try similar things. g++ warns for return X(); return static_cast<X&&>(x); but not return std::move(x); I expect the case of std::move to be important enough that if doing a generic warning is too hard, special-casing std::move could be worth the trouble (assuming it is easier).
(In reply to comment #3) > g++ warns for > > return X(); > return static_cast<X&&>(x); > > but not > > return std::move(x); Nor for X& g(X& x) { return x; } X& f() { X x; return g(x); } I opened PR 49974 to request a warning there, we don't need another :)
See also PR 51066 and PR 51270 and PR 38958 for similar RFEs for better diagnostics about creating dangling references