C++ Operator Overloading

The type of operator overloading that has some potential performance implications is one that returns an object of the type it operated on, usually binary operators. For example, operator+() is one of those operators. Consider the following code:

Vector3 velocity = oldVelocity + frameIncrement;
Vector3 propulsion = ComputePropulsion();
Vector3 finalVelocity = velocity + propulsion;

Vector3 class clearly has the operator+() function overloaded to add two 3D vectors together. The code looks clean and straightforward. Unfortunately  there is a hidden temporary in finalVelocity, operator+() is probably implemented like this.

const Vector3 operator+(const Vector3 &vecA, const Vector3 &vecB)
{
      return Vector3(vecA.x + vecB.x, vecA.y + vecB.y, vecA.z + vecB.z);
}

Notice that the return  type of the operator is not a reference or pointer, but an object itself. That means that the compiler first creates a temporary object, loads it with the result of the function and then copies it into the variable finalVelocity.

In this case, it might not be a big deal. After all, the Vector3 class is probably fairly lightweight and copying it a few times is not going to slow thing down much. That might be true, but the class might be copied more often than is apparent. What if that code were executed to update the particles in a particle-effect system? Then it would probably get executed many thousands of times per frame, which might begin to make a  difference.

The good news is that there is a way around it that still allows us to use operator overloading without incurring any extra performance over-head. The solution to replace binary operators of the form operator+() with unary operators of the from operator+=(). The latter type of operator acts directly on the object on which it was invoked, so there is no extra copying of temporaries. Here is the definition of operator +=().

Vector3 &Vector3::operator+=(const Vector3 &vec)
{
       x += vec.x;
       y += vec.y;
       z += vec.z;
 
       return *this;
}

Now we are not copying objects, we are just returning a reference to the object on which the function acted (by dereferencing the this pointer). The code that uses it would then look like this:

Vector3 velocity = oldVelocity + frameIncrement;
velocity += CommputePropulsion();

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s