This question already has answers here:
Is it counter-productive to pass primitive types by reference? [duplicate]
(7 answers)
Closed 7 years ago.
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
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.
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.
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.
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.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it better to pass by value or by reference for basic datatypes?
Reasons to not pass simple types by reference?
I did some testing where I had two scenarios, each with two identical functions- one passing the parameter by reference and the other by value. The scenario with strings showed a massive performance increase (because a copy of string is made, calling a constructor) whereas the test with long didn't show any performance increase when passing the value by reference. In fact, sometimes the performance was worse.
Is this expected with primitive types? Is there no point passing them by reference?
I was expecting a copy of a primitive type is made when not using by reference and therefore expected a small performance-boost.
You get the best performance from passing primitive types by value. This is because:
primitives are blitable, so the cost of the copy depends on the size
primitives are small, only double and long long are bigger than a reference in most environments
pass-by-value avoids aliasing, allowing the optimizer to really do its thing
This last point is often overlooked but can make a considerable difference.
Yes, that's the expected behavior. When you're passing parameters by reference, you're actually passing an address of the variable (like with pointer). Usually address is a 4 or 8-byte integer, so unless your primitive type is larger than that, you won't gain any performance improvement (and even if it's larger, you probably won't)
Modern compilers are pretty clever, so if the function isn't "hidden" (that is, part of something the compiler can't see at the time of producing the code), it may well make no difference at all. HOwever, if it the compiler follows your instructions, passing simple types as reference does potentially make a big difference. Particularly if the value is updated many times in the code.
I saw some code where I worked, which did something like this:
void SomeClass::FindLength(int &len)
{
listEntry* list = theList; // theList is a member variable.
len = 0;
while (list)
{
len++;
list = list->next;
}
}
By alterning the code to do:
void SomeClass::FindLength(int &len)
{
listEntry* list = theList; // theList is a member variable.
int tempLen = 0;
while (list)
{
tempLen++;
list = list->next;
}
len = tempLen;
}
the whole code ran some 30% faster, and called from a lot of places (and I think there was some if-condition in the middle, so we couldn't just keep track of the length). And since it was part of an API function, it wasn't possible to change the function signature.
The reason it was slower using the reference is that the compiler would write to the reference value EVERY time it was updated, which was a load from memory to register, increment register and a store register to memory. With the tempLen solution, the compiler could use a register, which is much faster.
In c++ reference is just convinient way to use pointers. When you use pointer you adding additional indirection. Copying primitive types as cheap as copying pointer.
That is why primitive types passed by reference a bit slower
Because you used c tag, I guess you are speaking about pointers (not explicit references from C++).
With pointers, you have two memory access: the pointer and the pointed value. So there is no particular gain of performances. Moreover, the compiler can do more optimisations with values: there is no aliasing problems, for example.
Is this expected with primitive types?
I'd say absolutely. They don't have constructors, so that doesn't need to be called.
Is there no point passing them by reference?
There is: when you want to have output parameters, then, in C++, passing by reference is considered better pracitce than passing a pointer.
I was expecting a copy of a primitive type is made when not using by reference and therefore expected a small performance-boost.
Well, since passing by reference is usually implemented using pointers, then the compiler has to emit code that pushes something onto the stack, either the value, or a pointer to the value - and it really does not matter which one is done.
When you pass a value by reference the function must dereference it to obtain the value, and each time you modify the value a dereference must occur too since you are writing it in a memory location. I guess compilers are able to understand when something won't be stored back in its reference location so that the value is modified just on registers and stored back just when needed but I'm not sure how powerful this is.
So there is an indirect step that is not present while passing parameters by value, which can cause worse performance but it's really foggy since compiler optimizations come into place. Think about the fact that you are passing a pointer, every time you need the value you must fetch the pointer from the stack and then fetch the value pointed (so there are two accesses), while with a normal parameter you have just one (fetching the value).
In any case, a reference is used for purposes that are surely different from performance, like modifying the passed parameter locally.
When passing parameters to functions and methods that will be called millions of times in a short amount of time, the overhead of passing said parameters begins to show.
void foo(const SomeType& st)
{
...
}
For types like std::string, std::vector etc... the rule is to pass by reference so that pointless copies don't occur. However when dealing with PODs such as doubles, ints etc, the story is quite different.
With regards to performance, If the function/method does not need to mutate the parameters, what are the common 'things to look out for' when deciding if one should pass by reference, const reference or copy?
void foo1(SomeType& st)
{
...
}
void foo2(const SomeType& st)
{
...
}
void foo3(SomeType st)
{
...
}
void foo4(SomeType* st)
{
...
}
Should an int/unsigned int always be passed by copy?
Should a double be passed by copy only on 64-bit or higher targets?
If the function can be inlined - does how the parameters are passed in matter?
How does aliasing affect problems when passing in by ref/const ref?
Under what circumstance would a explicit copy of the parameter be beneficial on the stack?
Note: This is a not a question about const-correctness. Also looking for answers relating to gcc and msvc on 32/64-bit platforms.
Some possibly related Q/As:
"const T &arg" vs. "T arg"
https://stackoverflow.com/a/2139254/754951
Pass by Reference / Value in C++
Why pass by const reference instead of by value?
The best answer is for you to read the calling conventions in your platform, but in general, for small types (those that fit in a register or even sometimes slightly bigger), it will usually be faster to pass by value. When you pass by pointer or reference a pointer is passed by value, which will have the same cost of copying the original object, plus it will require dereferences.
When the objects become big then the cost of copying the pointer plus the dereference will usually be smaller than the cost of copying a large object, so you should use references. If you don't intend to modify the object, pass const&.
Should an int/unsigned int always be passed by copy?
Should a double be passed by copy only on 64-bit or higher targets?
Even in 32bit architectures you should pass ints and doubles by value. Again, look at the calling conventions for your architecture (usually documented with the compiler).
If the function can be inlined - does how the parameters are passed in matter?
If the function is inlined the compiler can optimize it, and will for example, remove the cost of the reference by substituting the uses of the reference for the original object in place.
How does aliasing affect problems when passing in by ref/const ref?
If you are not going to modify the argument (as you claim in the question) aliasing will not matter. You will have aliasing problems if you pass pointers/references that can be modified in a way that the algorithm does not expect.
Under what circumstance would a explicit copy of the parameter be beneficial on the stack?
Ignoring the on the stack part: when the objects are small. Note that the calling convention used might not even use the stack (it might pass the value in a register). I recommend that you read this article on the different calling conventions
With C++ how do i decide if i should pass an argument by value or by reference/pointer? (tell me the answer for both 32 and 64bits) Lets take A. Is 2 32bit values more less or equal work as a pointer to a 32bit value?
B to me seems like i always should pass by value. C i think i should pass by value but someone told me (however i haven't seen proof) that processors don't handle values not their bitsize and so it is more work. So if i were passing them around would it be more work to pass by value thus byref is faster? Finally i threw in an enum. I think enums should always be by value
Note: When i say by ref i mean a const reference or pointer (can't forget the const...)
struct A { int a, b; }
struct B { int a; }
struct C { char a, b; }
enum D { a,b,c }
void fn(T a);
Now tell me the answer if i were pushing the parameters many times and the code doesn't use a tail call? (lets say the values isnt used until 4 or so calls deep)
Forget the stack size. You should pass by reference if you want to change it, otherwise you should pass by value.
Preventing the sort of bugs introduced by allowing functions to change your data unexpectedly is far more important than a few bytes of wasted stack space.
If stack space becomes a problem, stop using so many levels (such as replacing a recursive solution with an iterative one) or expand your stack. Four levels of recursion isn't usually that onerous, unless your structures are massive or you're operating in the embedded world.
If performance becomes a problem, find a faster algorithm :-) If that's not possible, then you can look at passing by reference, but you need to understand that it's breaking the contract between caller and callee. If you can live with that, that's okay. I generally can't :-)
The intent of the value/reference dichotomy is to control what happens to the thing you pass as a parameter at the language level, not to fiddle with the way an implementation of the language works.
I pass all parameters by reference for consistency, including builtins (of course, const is used where possible).
I did test this in performance critical domains -- worst case loss compared to builtins was marginal. Reference can be quite a bit faster, for non-builtins, and when the calls are deep (as a generalization). This was important for me as I was doing quite a bit of deep TMP, where function bodies were tiny.
You might consider breaking that convention if you're counting instructions, the hardware is register-starved (e.g. embedded), or if the function is not a good candidate for inlining.
Unfortunately, the question you ask is more complex than it appears -- the answer may vary greatly by your platform, ABI, calling conventions, register counts, etc.
A lot depends on your requirement but best practice is to pass by reference as it reduces the memory foot print.
If you pass large objects by value, a copy of it is made in memory andthe copy constructor is called for making a copy of this.
So it will take more machine cycles and also, if you pass by value, changes are not reflected in the original object.
So try passing them by reference.
Hope this has been helpful to you.
Regards, Ken
First, reference and pointers aren't the same.
Pass by pointer
Pass parameters by pointers if any/some of these apply:
The passed element could be null.
The resource is allocated inside the called function and the caller is responsible should be responsible for freeing such a resource. Remember in this case to provide a free() function for that resource.
The value is of a variable type, like for example void*. When it's type is determined at runtime or depending on the usage pattern (or hiding implementation - i.e Win32 HANDLE), such as a thread procedure argument. (Here favor c++ templates and std::function, and use pointers for this purpose only if your environment does not permit otherwise.
Pass by reference
Pass parameters by reference if any/some of these apply:
Most of the time. (prefer passing by const reference)
If you want the modifications to the passed arguments to be visible to the caller. (unless const reference is used).
If the passed argument is never null.
If you know what is the passed argument type and you have control over function's signature.
Pass by copy
Pass a copy if any/some of these apply:
Generally try to avoid this.
If you want to operate on a copy of the passed argument. i.e you know that the called function would create a copy anyway.
With primitive types smaller than the system's pointer size - as it makes no performance/memory difference compared to a const ref.
This is tricky - when you know that the type implements a move constructor (such as std::string in C++11). It then looks as if you're passing by copy.
Any of these three lists can go more longer, but these are - I would say - the basic rules of thumb.
Your complete question is a bit unclear to me, but I can answer when you would use passing by value or by reference.
When passing by value, you have a complete copy of the parameter into the call stack. It's like you're making a local variable in the function call initialized with whatever you passed into it.
When passing by reference, you... well, pass by reference. The main difference is that you can modify the external object.
There is the benefit of reducing memory load for large objects passing by reference. For basic data types (32-bit or 64-bit integers, for example), the performance is negligible.
Generally, if you're going to work in C/C++ you should learn to use pointers. Passing objects as parameters will almost always be passed via a pointer (vs reference). The few instances you absolutely must use references is in the copy constructor. You'll want to use it in the operators as well, but it's not required.
Copying objects by value is usually a bad idea - more CPU to do the constructor function; more memory for the actual object. Use const to prevent the function modifying the object. The function signature should tell the caller what might happen to the referenced object.
Things like int, char, pointers are usually passed by value.
As to the structures you outlined, passing by value will not really matter. You need to do profiling to find out, but on the grand scheme of a program you be better off looking elsewhere for increasing performance in terms of CPU and/or memory.
I would consider whether you want value or reference semantics before you go worrying about optimizations. Generally you would pass by reference if you want the method you are calling to be able to modify the parameter. You can pass a pointer in this case, like you would in C, but idiomatic C++ tends to use references.
There is no rule that says that small types or enums should always be passed by value. There is plenty of code that passes int& parameters, because they rely on the semantics of passing by reference. Also, you should keep in mind that for any relatively small data type, you won't notice a difference in speed between passing by reference and by value.
That said, if you have a very large structure, you probably don't want to make lots of copies of it. This is where const references are handy. Do keep in mind though that const in C++ is not strictly enforced (even if it's considered bad practice, you can always const_cast it away). There is no reason to pass a const int& over an int, although there is a reason to pass a const ClassWithManyMembers& over a ClassWithManyMembers.
All of the structs that you listed I would say are fine to pass by value if you are intending them to be treated as values. Consider that if you call a function that takes one parameter of type struct Rectangle{int x, y, w, h}, this is the same as passing those 4 parameters independently, which is really not a big deal. Generally you should be more worried about the work that the copy constructor has to do - for example, passing a vector by value is probably not such a good idea, because it will have to dynamically allocate memory and iterate through a list whose size you don't know, and invoke many more copy constructors.
While you should keep all this in mind, a good general rule is: if you want refence semantics, pass by refence. Otherwise, pass intrinsics by value, and other things by const reference.
Also, C++11 introduced r-value references which complicate things even further. But that's a different topic.
These are the rules that I use:
for native types:
by value when they are input arguments
by non-const reference when they are mandatory output arguments
for structs or classes:
by const reference when they are input arguments
by non-const reference when they are output arguments
for arrays:
by const pointer when they are input arguments (const applies to the data, not the pointer here, i.e. const TYPE *)
by pointer when they are output arguments (const applies to the data, not the pointer)
I've found that there are very few times that require making an exception to the above rules. The one exception that comes to mind is for a struct or class argument that is optional, in which case a reference would not work. In that case I use a const pointer (input) or a non-const pointer (output), so that you can also pass 0.
If you want a copy, then pass by value. If you want to change it and you want those changes to be seen outside the function, then pass by reference. If you want speed and don't want to change it, pass by const reference.
Here's a tip that makes some confusions for me:"to have the best passing method pass built-in types by value and other types by reference to constant" now I have some questions below:
1-first of all I think the reason behind suggesting passing by reference to constant is that if the referenced object is not volatile the compiler can convert it to pass by value if it would be more efficient but it would have made more sense to me if there was a special syntax by which we could tell the compiler ok here determine the best passing method yourself I don't care how it will be but changing pass by reference to constant to pass by value by compiler seems messy somehow to me, in the way it is now if we want the compiler to obey the pass by reference to constant and use a pointer we have to force it to do so since it may determine the more efficient way is to pass by value; so can you lighten me up why it is this way that this is?.
2-Does "pass built-in types by value" include built-in types that are bigger in size than size of a pointer like long double on my platform that has 8 bytes comparing to pointer size that is 4 bytes and does "pass non-built-in types by reference to constant" include things like below that likely can be transfered in memory like built-in types:
struct Test1{
public:
char characters[2];
};
struct Test2{
public:
char characters[4];
};
a special syntax by which we could
tell the compiler ok here determine
the best passing method yourself
Boost provides this, as boost::call_traits<T>::param_type.
why it is this way that this is
Probably because the rule of thumb works most of the time. If in doubt, you can pass by const reference and it's unlikely to be horribly inefficient.
In fact there's more to the general tip than you say - "small" types which aren't built-in are also usually best passed by value. For example, the standard library consistently passes iterators by value.
Does "pass built-in types by value"
include built-in types that are bigger
in size than size of a pointer
Yes. You can reasonably expect a C++ implementation to pass a double or long double by value with acceptable efficiency for almost all practical purposes. If you've reached the stage of optimization where this is the lowest-hanging fruit, then you're beyond general tips. You would measure both in your actual program.
if the referenced object is not
volatile the compiler can convert it
to pass by value if it would be more
efficient
Maybe. If the call is successfully inlined, then the compiler can do pretty much anything. If the call target isn't available to the compiler, then it can't do it, because in practice a change between value vs. const reference parameter requires changes to both the caller and the callee code. Furthermore, aliasing means that unless the compiler has a lot of information about what's going on, then even with a non-volatile object it can't necessarily assume that it won't change:
int foo(const int &a, int &b) {
b = 2;
return a;
}
Unless it's inlined, this code cannot be changed to pass a by value, because someone might call it like this:
int a = 1;
std::cout << foo(a,a);
which must print "2", whereas with a passed by value it would print "1".
Re "in the way it is now if we want the compiler to obey the pass by reference to constant and use a pointer we have to force it to do so since it may determine the more efficient way is to pass by value"
No, a compiler can only replace pass-by-ref-to-const with pass-by-value if it can prove that there will be no aliasing (e.g. f calling g which happens to use a pointer to original actual argument to change that argument's value underfoot, so to speak). Generally there will be no problematic aliasing. But proving it is generally difficult.
The upshot is that where you pass by reference, the argument will really be passed by reference unless the call is inlined. And where the compiler does change pass-by-ref-to-const to pass-by-value, if that should happen, then it's where the compiler has proved that nothing is done that could be affected. So you're safe.
Cheers & hth.,
The compiler would likely optimize the parameter passing as it feels best. I don't know in this specific example, but generally speaking, the compiler makes all sorts of front-end and back-end optimizations at each step. So, I don't think you'd need to pass any "special syntax" to the compiler.
Yes, pass-by-value means just that even if the primitive/built-in data type were larger than a memory pointer or register. On 32-bit architectures, doubles (64 bits/8 bytes) and long doubles (80 bits/10 bytes) occupy multiple registers.
Does "pass built-in types by value" include built-in types that are bigger in size than size of a pointer like long double on my platform that has 8 bytes comparing to pointer size that is 4 bytes.
Yes, because those can usually passed in a register which is as efficient as it gets. The only time when passing by const reference might be faster is when you pass something that is already stored in a variable. (But then you pay the extra cost of dereferencing in the callee). Most of the times though, the caller's arguments are arbitrary expressions like a * b + c, and it would be inefficient to first store the result in memory and then pass it indirectly via reference to const.
Two questions rolled into one here...
I have a number of functions which are called multiple times per frame for a real-time video processing application. Taking advice about const and pass by reference, the functions have a signature somewhat like this
void processSomething(const int& value);
As I keep typing the few extra characters, I am wondering if this is overkill.
Second question, well, on the subject of pass by reference, within the slots/signals mechanism of QT, does pass by reference helps to prevent copying of objects as in a normal function call?
Yes, this is overkill and will actually result in slower code than if you passed the int by value. An int is four bytes; a reference (essentially a memory address) is either also four bytes (on a 32-bit machine) or eight bytes (on a 64-bit machine). So you may actually need to pass more information to the function -- and additionally, you have the overhead of dereferencing that reference.
If you're passing something bigger than an int, however, it's more efficient to use a const reference, because you can pass just four or eight bytes instead of having to copy the whole object.
Edit Regarding Qt: Yes, if the slot takes a const reference to an object, then the reason for that is to save the overhead of copying the object.
Yes, pass by reference helps against copying the objects. But the compiler might decide to optimize it out entirely and insted pass by value if it produces the same effect. Such optimization is usually possible if the function and the call site are in the same translation unit but some compilers can do even more global optimizations - you can inspect the emitted assembly if you care.
This is why you really shouldn't pass primitive types by reference if you care about performance and unless you really have reasons for that. See What is the use of passing const references to primitive types? for discussion of that problem.
First - the difference between
void processSomething(const int& value);
void processSomething(int value);
is: normally a const reference is passed by passing a pointer, the other thing is passed by copying. After the call (from the caller side) the result is equal. Whatever you pass to the function is not changed by the call.
Inside the function you won't see any differences either (at least on an int). On Objects, you may only use const functions of course.
On the performance side - passing a const reference to an int may (or may not) be slower, depending on compiler and optimization. The compiler could (in theory) optimize the passing of the const reference away to a pass by value, I don't know if it does though. Working with pointers to ints instead of values is slower of course.
For more information on that see:
When to use pointers, and when not to use them
After reading the other linked post - the compiler can not optimize it away in a multithreaded environment. At least in a MT-environment there are real differences betwenn const int& and int calls. +1 for that link.