Returning from a function (whose return type is a reference type) initializes a reference. For example, within
f, the statement
return 42;
initializes a
int const& with
42 as the initializer. The newly-initialized reference is what is returned from the function.
References are aliases for
objects, which have a
lifetime. The hidden
int const& initialized by
return 42 refers to an object whose lifetime ends at the end of the return statement.
As a result, the function always returns a reference to an object that has already ceased to exist -- a
dangling reference.
The first function results in some compiler warnings:
GCC wrote: |
---|
warning: returning reference to temporary [-Wreturn-local-addr] |
Clang wrote: |
---|
warning: returning reference to local temporary object [-Wreturn-stack-address] |
MSVC wrote: |
---|
warning C4172: returning address of local variable or temporary |
S.A.:
http://www.cplusplus.com/forum/general/275104/#msg1187301
The issue with the second function is almost the same. Within
g, the statement
return x; initializes a hidden
int& using
x as the initializer. Only the lifetime of the referenced object
x is different. It lives until the (imminent) end of the function, and not an instant more. Therefore
g also returns a dangling reference.
The second function produces compiler warnings similar to
f.
Finally the problem with
h is very subtle; the compiler is no help. If the expression
e is a prvalue expression, using
h(e) to initialize a reference, as in
int const& r = h(42);
Initializes
r to refer to a materialized temporary object -- the same object bound to
h's formal parameter.
r becomes a dangling reference at the semicolon.
The point is that returning by reference is really tricky, even for experienced programmers. It can only be done correctly with a guarantee that the object being referenced lives long enough to be useful.