Reputation: 24089
Consider these two functions.
int foo(const int& a) {
return a + 5;
}
int bar(const int a) {
return a + 5;
}
Given these functions, g++-4.9 generates the following code at full optimization.
g++-4.9 -std=c++11 -Ofast -march=native -DNDEBUG -fno-exceptions -Wall -S -o test17.S test17.cpp
# foo
movl (%rdi), %eax
addl $5, %eax
ret
# bar
leal 5(%rdi), %eax
ret
The machine is an x86-64 Mac.
Why is the compiler so "literal minded" here?
My understanding is that references in C++ are usually implemented as pointers but that this is not mandated by the standard. They are best understood as an alias for a variable. The details are left to the implementation.
Given that references need not actually be pointers, it seems like an obvious optimization to generate the same code for both functions. Would it have been illegal to generate the const int
code for both of these functions? Is there an observable difference between the two functions?
Upvotes: 1
Views: 135
Reputation: 320631
You declared your functions with external linkage. A compiler that does not (or cannot) perform global program optimizations cannot change interface specification of a function with external linkage for obvious reasons - that function can be called from some other translation unit, which has no knowledge of whether the function's interface specification was "transformed" or not.
If you declare these functions with internal linkage, then the compiler will have much more freedom in transforming these functions.
When I declared your functions static
and compiled them with gcc -O3 -fno-inline-functions -fno-inline-functions-called-once -fno-inline-small-functions
(in a desperate no-holds-barred attempt to kill any possibility of inlining), they produced identical code
_ZL3bari:
.LFB1:
.seh_endprologue
leal 5(%rcx), %eax
ret
_ZL3fooRKi.isra.0:
.LFB3:
.seh_endprologue
leal 5(%rcx), %eax
ret
Note that these considerations apply to "trivial" functions only (which is probably what you meant in the first place) with "obvious" (to the compiler) semantics. A "non-trivial" function might cast away the constness of the reference and modify the referee, which is perfectly legal provided the referee itself is modifiable. For this reason in general case it is not possible to replace a const reference parameter with a value parameter.
Upvotes: 9