Returning from a function (whose return type is a reference type) initializes a reference. For example, within f
, the statement
initializes a int const&
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:
|warning: returning reference to temporary [-Wreturn-local-addr]|
|warning: returning reference to local temporary object [-Wreturn-stack-address]|
|warning C4172: returning address of local variable or temporary|
The issue with the second function is almost the same. Within g
, the statement return x;
initializes a hidden int&
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);
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.