The Magic of C++11's 'auto'
At first glance, it seems like the main benefit of using 'auto' is the improvement of code readability for example, when declaring an iterator for an 'stl' container in a 'for loop' it's nice to keep it short.
Or when using templates things can get really messy like -
someWeirdTemplate<someOtherVeryLongNameType, ...> ::someOtherLongType x = GetX();
VS
auto x = GetX();
The question is, can the use of 'auto' also improve the performance of your program?
This question was asked on stack overflow, and an interesting answer (by Barry) claiming there's better performance when using 'auto' caught my attention, the example he gives is as follows:
std::map<Key, Val> m;
for (std::pair<Key, Val> const& item : m)
{
// do stuff
}
VS
std::map<Key, Val> m;
for (auto const& item : m)
{
// do stuff
}
I decided to test the differences and did so in three different ways:
All tests lead to Barry's conclusion, there is definitely a performance improvement when using 'auto'.
Benchmark:
The results show using 'auto' in this case, is 2.6 times more efficient
as demonstrated in this diagram:
Assembly code:
When not using 'auto' the assembly code is nine lines longer.
Here are the added lines:
Recommended by LinkedIn
Compiler Analysis:
There is an amazing tool I recently discovered, created by Andreas Fertig (link below). This tool shows the 'heavy lifting' done by the compiler behind the scenes.
Here is a screenshot of the lines where the compilers' work differs when running the two versions of the example above.
Examine the differences:
You can see that when not using 'auto' the compiler calls the 'pair's' constructor in the 'for loop' to instantiate a temporary, meaning a copy is created per iteration for each element in the map.
But wait a second, why is that happening Didn't we declare a reference? Why are we getting a copy?!
On the other hand when using 'auto' all the compiler does is - get a reference to the objects as per iteration,
oh.. and one more thing - the const qualifier is added to the key,
this is the "key" to understanding what is happening.
Understanding the magic:
When iterating over a map the key which is returned is a const, and since const was not declared (for the key), the compiler must 'cast away' the const by converting the returned value thus creating a temporary copy per iteration (yes.. a const reference can be bounded to an R-value), this is highly inefficient.
When using 'auto', the compiler adds const to the key, avoiding the need for conversion and preventing unnecessary copies.
link to stack overflow:
link to benchmark: https://quickbench.com/q/wx58vKETi74WMYlDCILPHm5Alck
link to the assembly code:
link to the Compiler Analyse:
I find 'auto' less readable not knowing the type of the variable and having to dig deep to find out.