8

When I pass primitives like int and double to functions , is it better to pass them by const reference , or by value (assuming that I don't change the variable's value) ?

int getValueFromArray(int index)
{
    // return the value from the array
}


int getValueFromArray(const int& index)
{
    // return the value from the array
}

Thanks

JAN
  • 21,236
  • 66
  • 181
  • 318

4 Answers4

10

For primitive types, passing by value is much better than passing by reference. Not only is there no indirection, but with a reference, the compiler has to worry about potential aliasing, which can ruin optimization opportunities.

Finally, pass-by-reference causes lvalues to become odr-used, which can actually cause linker errors. And this final issue doesn't go away if the call gets inlined.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
1

A lot depends on the compiler's optimization level. Compiler optimizations may make the whole point moot. Also the implementation architecture plays a role, somewhat. But, in general, passing by value should be slightly better.

It helps to understand that a reference is really just a pointer, with some sugar on top. So, retrieving the value of the parameter involves getting this pointer parameter off the stack, then making another dereference, to obtain the value, versus reading the value of the parameter directly off the stack.

But the differences are mostly academical in nature. This question becomes more important when the parameter is more than just an int value. Then, the choice comes down to passing a reference, with no further work needed, versus making a copy of the instance of the parameter class. Which can be expensive.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
1

If you pass the int by const reference, you'll end up paying the penalty of one (unnecessary) layer of indirection to access its value unless a very smart optimizer detects that it's OK to just pass the int by value under all circumstances.

Sometimes passing and int by (const) reference makes sense, but really only if you are writing templated code and don't want to create additional specializations for primitive data types like int. Under normal circumstances you are better off passing the int by value instead of const reference, especially as on a lot of hardware, the int can be passed into the function in a register when you're dealing with functions with signatures like the ones you have above. And even if not, it's right there on the stack with good locality of reference.

With a double the picture changes somewhat because on some architectures it's more efficient to pass a reference or pointer to a double into a function rather than the value itself. However on recent hardware, you're most likely to lose performance due to the layer of indirection compared to just passing the value.

In both cases, a compiler/linker with fairly aggressive inlining and especially link time code generation would be able to optimize the code to avoid any parameter passing on the stack if you're dealing with smaller utility functions that the code generator will inline.

Timo Geusch
  • 24,095
  • 5
  • 52
  • 70
1

If the data type can fit into a processor's register, pass by copy (value). Larger items should be passed by reference.

You should print out the assembly language listing for both examples, at no optimizations and high optimizations. With better compilers, the compiler will recognize the pattern and perform the best choice, usually passing by value.

In the assembly language listing, you could see how the compiler performed any optimizations.

Worst case of no optimization, a constant reference usually is implemented by passing by pointer. So instead of having the value in a register, the pointer will be in the register. This means that whenever you access the variable, you are dereferencing a pointer first. This may be a few extra instructions or processor cycles, but may not be significant, in both execution and program space.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154