|
Boost : |
From: Darin Adler (darin_at_[hidden])
Date: 1999-12-29 12:28:30
> The semantics are the same (except for the number of temporary objects):
>
> Return-by-const-reference ("const T & func();")
>
A:
> T x(func()); // initializes x with the object referred to by func().
> // No temporaries.
B:
> const T & x = func(); // x refers to what func() referred to. No
> // temporaries.
>
> Return-by-value ("T func();")
>
C:
> T x(func()); // initializes x with the return value of func. One
> // temporary.
D:
> const T & x = func(); // binds x to a temporary constructed from the
> // return value of func(). One temporary
> // (not including the one bound to x).
>
> The problem with return-by-const-reference is that the object must actually
> be persistent in memory -- it cannot be a Mayfly (generated on-the-fly)
> object. So I find return-by-value useful in requirements specifications,
> make a note that temporary objects required by return-by-value semantics may
> not actually ever exist, and implement using return-by-const-reference
> whenever possible.
I agree that A and C above are equivalent.
But B and D are not.
In B, the lifetime of the object referenced by "x" is determined by func().
If func() returns a reference to a member of an object, "x" will only be
valid as long as that object is alive. After that, use of "x" will result in
undefined behavior.
In D, the lifetime of the object referenced by "x" is determined by the
lifetime of "x". As long as "x" is still in scope, the object is guaranteed
to be good.
This is a significant difference that can cause real trouble in practice. I
believe that returning a const reference is an idiom that trades a bit of
efficiency for a subtle danger of a dangling reference.
-- Darin
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk