Consider the following function:
template <class T, class Priority>
void MutableQueue<T, Priority>::update(const T& item, const Priority& priority)
{
...
}
Would modern x86-64 compilers be smart enough to pass the priority argument by value rather than reference if the priority type could fit within a register?
Passing by const reference is the preferred way to pass around objects as a smart alternative to pass-by-value.
Pass-by-reference means to pass the reference of an argument in the calling function to the corresponding formal parameter of the called function. The called function can modify the value of the argument by using its reference passed in. The following example shows how arguments are passed by reference.
Passing primitive types in function: Primitive types are always passed by value. These are immutable. This means that even if we change the value in the function, the original value will not change. There are a total of five primitive data types in JavaScript.
If you recall, using pass by reference allows us to effectively “pass” the reference of a variable in the calling function to whatever is in the function being called. The called function gets the ability to modify the value of the argument by passing in its reference.
Compiler may do the optimization, but it is not mandatory.
To force to pass the "best" type, you may use boost: http://www.boost.org/doc/libs/1_55_0/libs/utility/call_traits.htm
Replacing const T&
(where passing by value is correct) by call_traits<T>::param_type
.
So your code may become:
template <class T, class Priority>
void MutableQueue<T, Priority>::update(call_traits<T>::param_type item,
call_traits<Priority>::param_type priority)
{
...
}
As @black mentioned, optimizations are compiler and platform dependent. That said, we typically expect a number of optimizations to happen day-to-day when using a good optimizing compiler. For instance, we count on function inlining, register allocation, converting constant multiplications and divisions to bit-shifts when possible, etc.
To answer your question
Would modern x86-64 compilers be smart enough to pass the priority argument by value rather than reference if the priority type could fit within a register?
I'll simply try it out. See for your self:
This is the code:
template<typename T>
T square(const T& num) {
return num * num;
}
int sq(int x) {
return square(x);
}
GCC -O3
, -O2
, and -O1
reliably perform this optimization.
Clang 3.5.1, on the other hand, does not seem to perform this optimization.
Should you count on such optimization happening? Not always, and not absolutely--the C++ standard says nothing about when an optimization like this could take place. In practice, if you are using GCC, you can 'expect' the optimization to take place.
If you absolutely positively want to ensure that such optimization happens, you will want to use template specialization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With