should I take arguments to inline functions by reference or value?

rlbond picture rlbond · Apr 6, 2009 · Viewed 10.9k times · Source

Is one of these faster?

inline int ProcessByValue(int i)
{
    // process i somehow
}

inline int ProcessByReference(const int& i)
{
    // process i somehow
}

I know that integral types should be passed by value. However, I am concerned that the compiler might inline ProcessByValue to contain a copy. Is there a rule for this?

Answer

jalf picture jalf · Apr 6, 2009

It doesn't make a difference. In both case, the code will be inlined to the same. Needlessly copying the int (in pass-by-value) will be eliminated by the compiler, and needlessly creating a reference to the int, and following that layer of indirection when accessing the int, will also be eliminated.

Your question seems to be based on some false assumptions:

  • That the inline keyword will actually get your function inlined. (It might, but that's certainly not guaranteed)
  • That the choice of reference vs value depends on the function being inline. (The exact same performance considerations would apply to a non-inlined function)
  • That it makes a difference, and that you can outsmart the compiler with trivial changes like this (The compiler will apply the same optimizations in either case)
  • And that the optimization would actually make a measurable difference in performance. (even if it didn't, the difference would be so small as to be negligible.)

I know that integral types should be passed by value. However, I am concerned that the compiler might inline ProcessByValue to contain a copy. Is there a rule for this?

Yes, it will create a copy. Just like passing by reference would create a reference. And then, at least for simple types like ints, the compiler would eliminate both again. Inlining a function is not allowed to change the behavior of a function. If you create the function to take a value argument, it will behave as if it was given a value argument, whether or not it's inlined. If you define the function to take a reference, it will behave as if passed a reference, whether or not it's inlined. So do what leads to correct behavior.