[ [ + operator ] ]
What are the significant differences in terms of performance
|
Absolutely nothing. The two are identical apart from syntax. I generally prefer the member function approach (as opposed to the friend function) because writing global functions when I don't need to makes me feel dirty, but it really doesn't matter.
a side-question: double or double& ? |
For basic data types (like double), I pass by value (so
double
), the reason is that passing by reference requires an indirection which may be slower than a variable copy.
For large objects (like classes), you're better off passing by reference because copying can be expensive.
But for a small function like this it doesn't matter whether your use double or double&, because the compiler will probably keep the value in a register anyway.
but back to the point, if I choose the second one in the previous example, I'd better write line 4 as friend Foo operator* (const Foo&, const double&); .
|
That's completely up to you. I generally do this:
1 2 3 4 5 6 7 8
|
class Foo
{
public:
Foo operator + (const Foo& rhs) { /* put actual code here */ } // "meat" function
Foo operator + (double rhs) { return *this + Foo(rhs); } // calls the "meat"
};
Foo operator + (double lhs, const Foo& rhs) { return Foo(lhs) + rhs; } // calls the "meat"
|
No need for friend declarations, and only have to write the "meat" code once.
But again it's all personal preference. If you'd rather make them all global/friend functions, you can. It's just a matter of style. It does not impact performance at all.
do these operators conventionally have a this pointer? |
The member functions do. The global/friend functions do not.
For the operators like operator+ and operator+=, which should call which, again speaking in terms of performance?: |
+ should call +=
|
*this = *this + rhs; // Hmm...is this line good?
|
This creates a temporary object, reassigns it to *this, then destroys it. Creation of the temporary object was wholley unnecessary. It's better to avoid it:
1 2 3 4 5 6 7 8 9 10 11
|
Foo& Foo::operator += (const Foo& rhs)
{
// no object copy
data += rhs.data;
return *this;
}
Foo Foo::operator + (const Foo& rhs)
{
return Foo(*this) += rhs; // calls +=
}
|
This might not be completely ideal in all situations, though. There may be instances where you might want to write code for + and += separately instead of having one call the other.