C++ Programming. Using the auto keyword
How to use the auto keyword
The auto
keyword changed its semantics starting from the C++11 standard. In this notebook, we will review its new semantics and examine its new flavors.
The auto
keyword changed its semantics starting from the C++11 standard. From C++11 onwards, the semantic of the keyword is
automatic type deduction. In fact, from C++11 onwards, we have the following different flavors
of the keyword [1]:
auto
const auto&
auto&
auto&&
Furthermore, we have decltype(auto)
. This post is a short guide on how to use auto
and its various flavors.
The first thing to note about auto
is that it ise used for automatic type deduction. This means that we can write code like the following:
...
// before c++11
int x = 5;
//from c++11
auto x = 5;
...
Thus, using auto
may help us to write cleaner and less cluttered code. This is emphasized particularly when we consider function signatures. Compare the code snippet below (example taken from [1]):
class Foo
{
int value()const{..}
const int& cref_value()const{...}
int& ref_value(){...}
};
with the following code snippet
class Foo
{
auto value()const{..}
auto& cref_value()const{...}
auto& ref_value(){...}
};
The latter API is obviously cleaner and simpler.The type returned is deduced by the compiler for us.
Remark
Althgough to a large extent using auto
simplifies our code, overusing it can have the opposite result.
One other advantage of using auto
is that we cannot leave the variable uninitialized. That is the following fails to compile.
...
auto x;
...
This is reasonable as the compiler uses the right hand side value to deduce the type and hence the memory size it has to allocate. If there isn't a value there is nothing
to deduce from. Thus, uninitialized variables are not allowed when using auto
and the good news are that the compilers let us know the exact line number in our code that this
occurs.
const auto&
has the ability to bind to anything [1]. The original object cannot be mutated via such a reference. Note that if the const
reference is bound to a temporary object, the lifetime of the temporary will be extended to the lifetime of the reference [1].
Although we may be using auto&
, it is possible that we end up with a const
reference. For example
auto foo = Foo{};
auto& cref = cref_value();
We should however strive to be more explicit and for such cases simply use const auto&
and use auto&
to only denote mutable references [1].
Similar to auto&
, auto&&
can bind to anything. auto&&
is called a forwardin or universal reference [1]. Similar to const auto&
, auto&&
extends the lifetime of a temporary. However, in contrast to const auto&
, auto&&
allows us to mutate the objects it references including the temporaries.
Remark
Note that auto&&
and T&&
are interpreted as forwarding references only when used in a function template where T
is a template parameter of that function. However, using &&
with an explicit type e.g. std::vector<double>&&
denotes an rvalue reference and does not have the properties of a forwarding reference [1].
- Bjorn Andrist, Viktor Sehr,
C++ High Performance, 2nd Edition
, Packt Publishing