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?

Given the following code:

const double val = 3.14;
auto         y   = val;

What type is y?

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?

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

You have attempted of activities on this page