Function parameters as references

by .

Performance can be increased by using references instead of copying values as function arguments.

Take a look at this little function that takes two vectors and returns the angle between them:

// Angle between two vectors as radians
Real GetVectorAngle(Vector v1, Vector v2)
{
  return ACos(!v1 * !v2);
}

This function works fine, of course. But take a closer look at what happens when it is called.

A Vector consists of three Real values, which are 64 Bit long (on a 64 Bit system). Since two Vectors are passed to the function, both their values get copied to v1 and v2, resulting in 6×64 Bit = 384 Bit, or 48 Bytes being copied. This can be optimized by using references instead:

// Angle between two vectors as radians
Real GetVectorAngle(const Vector& v1, const Vector& v2)
{
  return ACos(!v1 * !v2);
}

Now, only two memory addresses are passed; v1 and v2 utilize the same memory locations as the variables that had been passed to the function. The values themselves are not copied, only the memory addresses (resulting in only 2×64 Bit = 128 Bit, or 16 Bytes being copied). The const statements, by the way, don’t actually make anything faster; they are just there to signalize that we won’t change v1 or v2.

Now, let’s take a look at the following code, taken from the CINEMA 4D API:

inline LVector Mix(const LVector &v1, const LVector &v2, LReal t)
{
  return v1 + t*(v2-v1);
}

As you can see, v1 and v2 are passed as const references. But why not t? The reason is easy: Since t is just a single Real, making it a reference would not improve anything, since a Real is of the same size as a memory address.

As a rule of thumb: When you’re passing structures that are bigger than a memory address (32 Bit on a 32 Bit system, or 64 Bit on a 64 Bit system), use a reference. Variables of the types String, Vector, Matrix as well as any struct should generally be passed as a reference.

Advertisements