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.
I think you're just considering too much, especially with the details of optimization.
For result = a + b + c + d;
, the author just want to state that 3 temporaries will be created, the 1st one is for the result of a + b
, then 2nd one is for the result of temporary#1 + c
, the 3rd one is for temporary#2 + d
and then it's assigned to result
. After that, 3 temporaries are destroyed. All the temporaries are only used as the intermediate results.
On the other hand, some idioms such like expression templates could make it possible to get the final result directly with elimination of temporaries.
Compiler may detect accumulation and apply optimizations but generally shifting and reducing an expression from left to right is somehow tricky as it may be hit by an expression of style a + b * c * d
It is more cautious to take approach of form:
a + (b + (c + d))
which will not consume a variable before it might be required by an operator with higher priority. But evaluating it requires temporaries.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With