A function should never return a reference to a local object/variable since such objects go out of the scope and get destroyed when the function returns.
Differently, the function can return a const or non const reference to an object whose scope is not limited by the function context. Typical example is a custom operator<<
:
std::ostream & operator<<(std::ostream &out, const object &obj)
{
out << obj.data();
return out;
}
Unfortunately, returning-by-value has its performance drawback. As Chris mentioned, returning an object by value involves the copy of a temporary object and its subsequent destruction. The copy takes place by means of either copy constructor or operator=
. To avoid these inefficiencies, smart compilers may apply the RVO or the NRVO optimizations, but there are cases in which they can't -- multiple returns.
The upcoming C++0x standard, partially available in gnu gcc-4.3, introduces the rvalue reference [&&] that can be used to distinguish a lvalue from a rvalue reference. By means of that, it's possible to implement the move constructor, useful to return an object partially avoiding the cost of copy constructor and the destructor of the temporary.
The move constructor is basically what Andrei envisioned some years ago in the article http://www.ddj.com/database/184403855 suggested by Chris.
A move constructor has the following signature:
// move constructor
object(object && obj)
{}
and it's supposed to take the ownership of the internals of the passed object leaving the latter in a default state. By doing that, copies of internals are avoided and the destruction of the temporary made easy. A typical function factory will then have the following form:
object factory()
{
object obj;
return std::move(obj);
}
The std::move()
returns a rvalue reference from an object. Last but not least, move constructors allow the return-by-rvalue-reference of non-copyable objects.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…