First, let's look into the things that come into play here:
(a) Extending lifetime of a temporary when it's used to initialize a reference - I learnt about it in this publication by Andrei Anexandrescu. Again, it feels weird but useful:
class Foo { ... }
Foo GetFoo() { return Foo(); } // returning temporary
void UseGetFoo()
{
Foo const & foo = GetFoo();
// ... rock'n'roll ...
foo.StillHere();
}
The rule says that when a reference is initialized with a temporary, the temporary's lifetime is extended until the reference goes out of scope. (this reply quotes the canon)
(b) Return Value Optimization - (wikipedia) - the two copies local --> return value --> local may be omitted under circumstances. That's a surprising rule, as it allows the compiler to change the observable behavior, but useful.
There you have it. C++ - weird but useful.
So looking at your scenarios
Scenario A: you are returning a temporary, and bind it to a reference - the temporary's lifetime is extended to the lifetime of l_Foo.
Note that this wouldn't work if GetFoo
would return a reference rather than a temporary.
Scenario B: Works, except that it forces a Construct-Construct-Copy-Cycle (which may be much more expensive than single construct), and the problem you mention about requiring a default constructor.
I wouldn't use that pattern to create a object - only to mutate an existing one.
Scenario C: The copies of temporaries can be omitted by the compiler (as of RVO rule). There is unfortunately no guarantee - but modern compilers do implement RVO.
Rvalue references in C++ 0x allows Foo to implement a resource pilfering constructor that not only guarantees supression of the copies, but comes in handy in other scenarios as well.
(I doubt that there's a compiler that implements rvalue references but not RVO. However there are scenarios where RVO can't kick in.)
A question like this requires mentioning smart pointers, such as shared_ptr
and unique_ptr
(the latter being a "safe" auto_ptr
). They are also in C++ 0x. They provide an alternate pattern for functions creating objects.