3.7. Keyword: auto
¶
In C++11, the auto specifier meaning has changed significantly from
it’s definition prior to C++11.
Prior to C++11, auto
designated variables assigned to the
automatic storage class duration.
Every variable is assigned a storage duration which limits its lifetime.
The automatic duration applied to local variables in a block scope.
Because it was the default storage duration for variables in a block,
it was rarely, if ever, used.
It is still the default storage duration for block variables,
but no C++11 keyword is reserved for this behavior.
Since C++11, auto specifier instructs the compiler to automatically deduce the type of a variable based on the initializer used.
auto new_variable = initial_value;
Since the initializer provides the information used to deduce the type,
an initial value is required when using auto
:
auto x = 3; // OK
auto y; // Not OK
auto int z; // Error in C++11
// This is how auto was used prior to C++11
You can use auto
in nearly any statement that includes an initializer:
auto x = 3; // x is an int
auto q = '?'; // q is a char
auto r = &x; // r is an int
// - a reference to a variable is implicitly dereferenced
auto i = 0, d = 0.0; // Error.
// If using auto to deduce multiple types,
// then the types must all match
auto i = 0, *p = &i; // OK. Both i and the pointer to i are int
This is a far better use for the keyword auto.
Later, we will see that some types are long and complicated -
having to type them out, as was required prior to C++11,
is a chore.
auto
frees us from having to declare a type the compiler already knows about.
Additionally, some types, such as those returned by lambda expressions,
are hidden from us - auto is the only option in these cases.
When variables are initialized using auto, they inherit the type from the initializer, but not its constness.
int val = 0;
int& ir = val;
auto x = ir;
What type is x?
If you said, int
, excellent job!
ir
is a reference to val
,
which makes ir
just another name for val
.
auto x = ir;
is exactly the same as if we had written
auto x = val;
here.
Given the following code:
const double val = 3.14;
auto y = val;
What type is y?
If you said, double
, excellent job!
Just because val
is const
,
it has nothing to do with whether y
is const
.
If we had wanted y
to be const
,
then we would have needed to say so:
const auto y = val;
The auto
keyword is a simple way to declare a variable that has a complicated type.
We will get into the details of using auto in this way in later sections.
But accept for now that
you can use auto to declare a variable where the initialization
expression involves iterators, templates, pointers to functions, or pointers to members.
You can also use auto
to declare and initialize a variable to a lambda expression.
You can’t declare the type of a lambda yourself because the type of a
lambda expression is known only to the compiler.
auto
is also commonly used when a type would be redundant, especially in
range-for loops:
std::vector<double> numbers = {1.1, 2.2, 3.3, 5.5, 8.8};
for (const auto& n: numbers) {
std::cout << n << '\n';
}
In this case, the compiler already knows the type stored in the vector
numbers.
It doesn’t need to be told again.
When first introduced to auto
, many programmers balk.
It feels sloppy and imprecise, and it seems as if we are sacrificing clarity.
In fact using auto
is just as strongly typed as a manual declaration
and it aids clarity because it forces delaying variable
declaration until you have a value to initialize it with.
Guideline
Prefer to declare local variables using auto x = expr;
when you don’t need to explicitly commit to a type.
It is efficient by default and guarantees that no implicit conversions
or temporary objects will occur.
It is important to note that auto
may not always deduce
the type you expect or the type you need.
For example:
auto s = "Hello, world!";
What type is s?
If you said, const char*
, excellent job!
If you guessed string
, you are not alone.
This is a common mistake and one that gives new C++ programmers a lot of headaches.
String literals in C++ are always const char*
.
If you need a std::string
, you have to explicitly declare it:
std::string s = "Hello, world!";
One final note.
The auto
keyword is a placeholder for a type,
but it is not a type.
Therefore, auto
cannot be used in casts or operators such as sizeof
and typeid
.
More to Explore
From: cppreference.com: The auto specifier and decltype specifier.
Herb Sutter’s GOTW blog