tags:

views:

514

answers:

7

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?

+9  A: 

The parameter should be typed according to what makes sense for the function.

If the function takes a primitive type, pass by value would make sense. Some people I know would complain if it were passed by const ref (as it's 'unnecessary'), but I don't think I'd complain. If the function takes a user defined type and doesn't modify the parameter, then pass by const ref would make sense.

If it's a user defined type and the parameter is modified, then the semantics of the function would dictate how it should be passed.

Michael Burr
+4  A: 

The compiler should be able to optimize an inline function so that either method will generate identical code. Do the one that is clearest.

If in doubt, try it out. Turn on your compiler's assembly listing output, and see if there's a difference.

Mark Ransom
+8  A: 

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.

jalf
A: 

The best way to figure this out is to create a testbed that does both, build optimized versions of the code, and check it out the assembly. You'll see immediately what's going on with your particular compiler and your particular use-case.

When it really gets down to it, do what you think a user of your class would expect from an interface. When you have it all built and working, measure and find out where your bottlenecks are. Chances are, any difference this might make (and it's unlikely to make any) will be drowned out by larger performance concerns elsewhere in your code.

dominic hamon
A: 

If your compiler isn't smart enough to optimize away the local copy that isn't modified, it probably isn't smart enough to optimize away the local reference. In which case it will be generating even more awful code for the pass-by-reference case (cause every access to be indirect).

Greg Rogers
A: 

A very short answer: when deciding whether to pass by reference or by value treat the inline and non-inline functions the same.

Dima
A: 

In the case of primitives it doesn't matter because you are only passing 4 bytes.

The reason for passing a reference is because it is 4 bytes in size and that's a drastic reduction size in the case of custom types and large strings.

The argument is for speed... usually.

In the case of an inline function, you'd want all types that aren't primitives to be passed by reference since you're telling the compiler to inline it in the first place.

Ice