Returning by value is just like passing by value - a copy is made. At least that's how you should think about it. In practice RVO might optimise the copy away whilst keeping the intent of the code the same.
There are at least a dozen other ways it could have been implemented too. Here's a few of them:
Code:
const MyClass MyClass::operator+(MyClass other) const {
other += *this;
return other;
}
Code:
const MyClass MyClass::operator+(MyClass other) const {
return other += *this;
}
Code:
const MyClass MyClass::operator+(const MyClass &other) const {
return MyClass(*this) += other;
}
The two-parameter non-member version, which is better as it allows implicit conversion of both arguments:
Code:
const MyClass operator+(const MyClass &lhs, const MyClass &rhs) {
return MyClass(lhs) += *rhs;
}
Even shorter variant on the above (though less symmetrical looking):
Code:
const MyClass operator+(MyClass lhs, const MyClass &rhs) {
return lhs += *rhs;
}
In every single one of the above, one copy is made of one of the parameters, the other parameter is added to this (without copying it), and the resulting value is copied upon the return.