I decided to ask this question after reading items 20 and 22 of the book "More Effective C++" by Scott Meyers.
Let's say you wrote a class to represent rational numbers:
class Rational
{
public:
Rational(int numerator = 0, int denominator = 1);
int numerator() const;
int denominator() const;
Rational& operator+=(const Rational& rhs); // Does not create any temporary objects
...
};
Now let's say that you decided to implement operator+
using operator+=
:
const Rational operator+(const Rational& lhs, const Rational& rhs)
{
return Rational(lhs) += rhs;
}
My question is: if the return value optimization were disabled, how many temporary variables would be created by operator+
?
Rational result, a, b;
...
result = a + b;
I believe 2 temporaries are created: one when Rational(lhs)
is executed inside the body of operator+
, and another when the value returned by operator+
is created by copying the first temporary.
My confusion arose when Scott presented this operation:
Rational result, a, b, c, d;
...
result = a + b + c + d;
And wrote: "Probably uses 3 temporary objects, one for each call to operator+
". I believe that if the return value optimization were disabled, the operation above would use 6 temporary objects (2 for each call to operator+
), while if it were enabled, the operation above would use no temporaries at all. How did Scott arrive at his result? I think the only way to do so would be to partially apply the return value optimization.
const Rational
- I mean skipconst
(but not related to question) – Michaeuoperator+
whenRational(lhs)
is executed to be able to calloperator+=
? If you consider those, the upper bound is 6? Or are those optimized out of existence in some way? – Postfreeoperator+
even without RVO since it's passed by const reference, not by value. Meanwhile with RVO, all those "return and pass somewhere else" temps are eliminated, and you end up with half the temporaries. – Urethroscopeoperator+
to another invocation ofoperator+
provided the operands are accepted by const ref. There's a temp involved local to the function, another to return without RVO, but not another to pass the result as an operand to another call tooperator+
. – Urethroscopeoperator+
, and each one creates two temporaries (one local, another to return the result by value without RVO). – Urethroscope