Why is this implementation:
T& T::operator+=(const T&) {
// ... implementation ...
return *this;
}
T operator+(const T& lhs, const T& rhs) {
T temp(lhs);
return temp += rhs;
}
more common than this one:
T& T::operator+=(const T& rhs) {
*this = *this + rhs;
return *this;
}
T operator+(const T& lhs, const T& rhs) {
// ... implementation ...
return some_result;
}
Is there any reason at all, or is it just a random coincidence that I've seen people implement it this way multiple times in the literature that I read, and never the other way around?
operator+
has to create a new object to hold the result. operator+=
doesn't need a new object.
If you write operator+=
in terms of operator+
, then you end up paying for an extra new object creation, an assignment (or swap), and a destruction, all of which you didn't need.
Besides that, on many processors, the hardware has direct support for +=
and similar operations where the result is stored back to one of the input registers, and none for storing to a third register (like +
).
BTW, there's a mistake in your (original, now edited) code that hides part of the extra work. You actually need:
T& T::operator+=( const T& rhs )
{
*this = *this + rhs; // creation of temporary, move assignment, and destruction of temporary
return *this;
}
Even worse, your (again original, now edited) suggested implementation of operator+
fails to return the new object properly, it returns a dangling reference instead. That's undefined behavior.
For those interested, the first operator+
implementation can be improved even further by using pass-by-value:
T operator+( T lhs, const T& rhs )
{
lhs += rhs;
return lhs;
}
Now if the left hand operand of operator+
is a temporary, the move constructor will be used, avoiding a copy. Although with NRVO, there probably isn't much advantage in the resulting code either way.