Just an observation I'd like to share: Assuming frob returns
"*this" there's a difference between
because the 2nd case probably disables NRVO unless the
compiler inlines the function and is smart enough to figure
out that the returned reference actually refers to 's'.
NRVO really only applies when the expression in the return
statement is simply the name of a local non-static variable.
Otherwise, it's RVO. If S::frob() returns an S, the compiler
will probably arrange for this to be constructed (in S::frob)
directly in the return value of foo. If S::frob() returns an S&
or an S const&, of course, the object that it refers to will be
copied---the compiler can't know that it is the same object as s
(and I'm not sure that even if it did, I'm not sure that
removing the copy would be legal.
That's the reason why I usually write
T operator+(T const& a, T const& b)
{
T r = a;
r += b;
return r;
}
T operator+(T const& a, T const& b)
{
T r = a;
return r += b;
}
for some custom "arithmetic-like" type T.
The other alternative I've seen is:
T operator+(T const& a, T const& b)
{
return T(r) += b;
}
Personally, I don't like it, but supposedly, it allows RVO.
(Although if operator+= returns a T&, and isn't inlined, I don't
quite see how; in general, if all you have is a reference, and
you need an object, I think you need a copy. The reference
could, after all refer to an object with static lifetime.)
Anyway, your point concerning references (you didn't mention
them, but I presume that that's what you meant) is well taken.
An expression in the return statement which evaluates to a
reference will likely inhibit RVO (and of course, is it isn't
the name of a non-static local variable, NRVO doesn't come into
play). So the rules are: single return statement, whose
expression doesn't have reference type. And if the expression
is simply the name of a variable, the named variable is a
non-static local variable.