C++11: Auto

We've already covered C++11 decltype and why you should start using C++11 features today. Now we will move on to one of the most widely supported C++11 features: the new auto keyword.;

auto is supported currently by g++ as of 4.4, clang and msvc since 10. So you are safe using it today if you don't need to support any older compilers.

The auto keyword is used to let the compiler determine the type of a variable. This seemingly simple concept can really help clean up your code in some situations.

For example:

std::vector<:string>::const_iterator itr = myvec.begin();

Now becomes:

auto itr = myvec.begin();

However, this tool creates some ambiguities we aren't really used to in C++. What is the type of auto itr above? Is it const_iterator or iterator?

Or how about this snippet?

auto s = *itr;

Is that an std::string or a const std::string &? Or something else? It turns out that it's std::string. This incurs a copy penalty that we might not be expecting. It was non-obvious (to me) that we can apply some modifiers to the auto keyword type to get the desired result:

const auto &s = *itr;

Stephan T. Lavavej in the GoingNative conference pointed out cases where not only can auto introduce some performance costs if we aren't paying attention, it can also increase performance when we aren't paying attention. There are cases where we might accidentally apply a built in conversion and not realize it.

struct A
{
};

struct B
{
  B(const A &);
};

A getAnA();

B a = getAnA(); // oops we just called a conversion, was that intentional?
auto a2 = getAnA(); // we get the exact type returned

This could potentially be very useful in the case where a complex function such as std::bind returns a complex templated type that we naturally assign to a more user friendly std::function. Avoiding the conversion to an std::function may save some compile and run time overhead. It could also potentially get in your way. The actual type returned by std::bind is unspecified. This may mean that on one platform the result of std::bind is callable (has an implemented operator()) and auto works like you would expect whereas on another platform it is not callable and you just unintentionally introduced a portability issue in your code.

It's clear that auto will go a long way towards cleaning up the way our C++ looks, but we will still have to be intelligent about what type it is choosing for us.

Comments

shoudn't this

std::vector<std::string>::const_iterator itr = myvec.begin();

be

std::vector<std::string>::const_iterator itr = myvec.cbegin();

I had not noticed that they had added cbegin and cend in C++11. But technically either should work, as iterator is convertable to const_iterator and const_iterator is returned if the container is const in the current context.

Your point does address the later question of "what is the type of itr in the following case: auto itr = myvec.begin()?" Using cbegin would have cleared up the question.

-Jason