If speed is a concern, you shouldn’t use operators because an extra copy operation is executed when the function returns.
I have to disagree. If you implement and use your class properly, and use a good compiler, the overhead can be close to, if not even equal to, zero.
Just take a look at this example I made in a few minutes. It may not be a completely correct implementation, but at least it’s not a bad one.
class vector3
{
public:
vector3() {return;}
vector3(const vector3 &v)
{
operator()(0) = v(0);
operator()(1) = v(1);
operator()(2) = v(2);
}
inline float &operator()(int n) {return _data[n];}
inline const float &operator()(int n) const {return _data[n];}
inline const vector3 operator +(const vector3 &rhs) const
{
vector3 tmp;
tmp(0) = operator()(0) + rhs(0);
tmp(1) = operator()(1) + rhs(1);
tmp(2) = operator()(2) + rhs(2);
return tmp;
}
inline const vector3 &operator =(const vector3 &rhs)
{
operator()(0) = rhs(0);
operator()(1) = rhs(1);
operator()(2) = rhs(2);
}
public:
float _data[3];
};
Just notice the use of function call operators instead of direct accsess to the data. Also notice the temporary vector in operator +, which is returned by value (which it have to).
I then made two functions to add two vectors and store the result in another vector. One which uses the operator +, and one which makes the componentwise addition manually (this is why I had to make the data public by the way, normally I would make it private).
void addVectorsOperator(vector3 &c, const vector3 &a, const vector3 &b)
{
c = a + b;
}
void addVectorsManual(vector3 &c, const vector3 &a, const vector3 &b)
{
c._data[0] = a._data[0] + b._data[0];
c._data[1] = a._data[1] + b._data[1];
c._data[2] = a._data[2] + b._data[2];
}
Here’s the assembly output from MSVC 6.
; 38 : c = a + b;
mov eax, DWORD PTR _a$[esp+8]
mov ecx, DWORD PTR _b$[esp+8]
fld DWORD PTR [eax]
fadd DWORD PTR [ecx]
fld DWORD PTR [eax+4]
fadd DWORD PTR [ecx+4]
fld DWORD PTR [eax+8]
fadd DWORD PTR [ecx+8]
mov eax, DWORD PTR _c$[esp+8]
fstp DWORD PTR _tmp$340[esp+20]
mov ecx, DWORD PTR _tmp$340[esp+20]
fxch ST(1)
fstp DWORD PTR [eax]
fstp DWORD PTR [eax+4]
mov DWORD PTR [eax+8], ecx
Notice how all the operator calls and the temporary copy are effectively optimized away by the compiler.
Here’s the manual way.
; 43 : c._data[0] = a._data[0] + b._data[0];
mov eax, DWORD PTR _a$[esp-4]
mov ecx, DWORD PTR _b$[esp-4]
mov edx, DWORD PTR _c$[esp-4]
fld DWORD PTR [eax]
fadd DWORD PTR [ecx]
fstp DWORD PTR [edx]
; 44 : c._data[1] = a._data[1] + b._data[1];
fld DWORD PTR [eax+4]
fadd DWORD PTR [ecx+4]
fstp DWORD PTR [edx+4]
; 45 : c._data[2] = a._data[2] + b._data[2];
fld DWORD PTR [eax+8]
fadd DWORD PTR [ecx+8]
fstp DWORD PTR [edx+8]
Sure, there is a little difference, but in my personal oppinion, the difference is so small that I would go for the operator + because it’s cleaner code.
If speed is a concern, I really recomend an algorithmic optimization instead of hunting a few cycles here and there.