But if the variables aren't later used, do C++11 compilers optimize
the code so the variables are considered to be rvalues and both
versions work exactly the same?
It is possible but it greatly depends on your types. Consider the following example with a POD type point
:
#include <cstdio>
struct point {
int x;
int y;
};
static point translate(point p, int dx, int dy) {
return { p.x + dx, p.y + dy };
}
static point mirror(point p) {
return { -p.x, -p.y };
}
static point make_point(int x, int y) {
return { x, y };
}
int main() {
point a = make_point(1, 2);
point b = translate(a, 3, 3);
point c = mirror(b);
std::printf("(x,y) = (%d,%d)\n", c.x, c.y);
}
I looked at the assembly code, here is what the whole program(!) was basically compiled into (so the code below is a C approximation of the generated assembly code):
int main() {
std::printf("(x,y) = (-4,-5)\n");
}
It not only got rid of all the local variables, it also did the computations at compile time! I have tried both gcc and clang but not msvc.
OK, so let's make the program a little more complicated so that it cannot do the computations:
int main(int argc, char* argv[]) {
int x = *argv[1]-'0';
int y = *argv[2]-'0';
point a = make_point(x,y);
point b = translate(a, 3, 3);
point c = mirror(b);
std::printf("(x,y) = (%d,%d)\n", c.x, c.y);
}
To run this code, you would have to call it like ./a.out 1 2
.
This whole program is reduced to this one (assembly rewritten in C) after optimization:
int main(int argc, char* argv[]) {
int x = *argv[1]-'0';
int y = *argv[2]-'0';
std::printf("(x,y) = (%d,%d)\n", -(x+3), -(y+3));
}
So it got rid of a, b, c
and all the functions make_point()
, translate()
and mirror()
and did as much computions as possible at compile time.
For the reasons mentioned in Matthieu M.'s answer, don't expect to happen so good optimizations with more complicated types (especially non-PODs).
In my experience, inlining is crucial. Work hard so that your functions can be easily inlined. Use link time optimizations.