The question: Is there benefit to passing an integral type by const reference as opposed to simply by value.
ie.
void foo(const int& n); // case #1
<
Don't do this. int
is the same size as pointer/reference on common 32-bit plattforms, and smaller on 64-bit, thus you could get yourself a performance disadvantage instead of a benefit. I mean, all function arguments are pushed onto stack in order so that a function can read them, and it will either be your int, or its address in the case of reference. Another disadvantage is that the callee will either access your n
through an indirection (dereferencing an address), or it will make copy on its stack as an optimization.
If you make some changes to an int passed by value, it might be written either back onto the place on the stack where it was passed, or onto a new stack position. The second case naturally isn't advantagous, but shouldn't happen. By consting you bar yourself from making such a change, but this would work the same with const int
.
In the proper inline case it doesn't matter, naturally, but keep in mind that not everything where you write inline, will be.
Passing a built-in int type by const ref will actually be a minor de-optimization (generally). At least for a non-inline function. The compiler may have to actually pass a pointer that has to be de-referenced to get the value. You might think it could always optimize this away, but aliasing rules and the need to support separate compilation might force the compiler's hand.
However, for your secondary question:
For very small inline functions, will the compiler have to make a copy of the integer in case #2? By letting the compiler know we won't change the reference can it inline the function call without needless copying of the integer?
The compiler should be able to optimize away the copy or the dereference if semantics allow it, since in that situation the compiler has full knowledge of the state at the call site and the function implementation. It'll likely just load the value into a register have its way with it and just use the register for something else when it's done with the parameter. Of course,all this is very dependent on the actual implementation of the function.
It's not only performance. A true story: this week I noticed that a colleague tried to improve upon the Numerical Recipes and replaced the macro
#define SHFT(a,b,c,d) do { (a)=(b); (b)=(c); (c)=(d); } while (0)
by this function
inline void Rotate(double& dFirst, double& dSecond, double& dThird, const double dNewValue)
{
dFirst = dSecond;
dSecond = dThird;
dThird = dNewValue;
} // Function Rotate
This would have worked, if he had passed the last parameter by reference, but as it is, this code
Rotate(dum,*fb,*fa,dum);
which was supposed to swap *fa and *fb no longer works. Passing it by reference without const is not possible, as in other places non-l-values are passed to the last parameter.
I actually find it irritating when somebody uses const references like this for the basic datatypes. I can't see any benefit of doing this, although it may be argued that for datatypes bigger than sizeof(pointer)
it may be more efficient. Although, I really don't care about such minute 'optimizations'.
A lot of people are saying there's no difference between the two. I can see one (perhaps contrived) case in which the difference would matter...
int i = 0;
void f(const int &j)
{
i++;
if (j == 0)
{
// Do something.
}
}
void g()
{
f(i);
}
But.. As others have mentioned... integers and pointers are likely to be of similar size. For something as small as an integer, references will decrease your performance. It probably won't be too noticeable unless your method is called a lot, but it will be there. On the other hand, under some circumstances the compiler may optimize it out.
I can't think of any benefit. I've even seen recommendation that when writing templates, you use meta-programming to pass integral types by value and only use const reference for non-integral types.