auto
(C++)
Deduces the type of a declared variable from its initialization expression.
Note
The C++ standard defines an original and a revised meaning for this keyword. Before Visual Studio 2010, the auto
keyword declares a variable in the automatic storage class; that is, a variable that has a local lifetime. Starting with Visual Studio 2010, the auto
keyword declares a variable whose type is deduced from the initialization expression in its declaration. The /Zc:auto[-]
compiler option controls the meaning of the auto
keyword.
Syntax
auto
declarator initializer;
[](auto
param1, auto
param2) {};
Remarks
The auto
keyword directs the compiler to use the initialization expression of a declared variable, or lambda expression parameter, to deduce its type.
We recommend that you use the auto
keyword for most situations—unless you really want a conversion—because it provides these benefits:
Robustness: If the expression's type is changed—including when a function return type is changed—it just works.
Performance: You're guaranteed that there's no conversion.
Usability: You don't have to worry about type name spelling difficulties and typos.
Efficiency: Your coding can be more efficient.
Conversion cases in which you might not want to use auto
:
You want a specific type and nothing else will do.
In expression template helper types—for example,
(valarray+valarray)
.
To use the auto
keyword, use it instead of a type to declare a variable, and specify an initialization expression. In addition, you can modify the auto
keyword by using specifiers and declarators such as const
, volatile
, pointer (*
), reference (&
), and rvalue reference (&&
). The compiler evaluates the initialization expression and then uses that information to deduce the type of the variable.
The auto
initialization expression can take several forms:
- Universal initialization syntax, such as
auto a { 42 };
. - Assignment syntax, such as
auto b = 0;
. - Universal assignment syntax, which combines the two previous forms, such as
auto c = { 3.14159 };
. - Direct initialization, or constructor-style syntax, such as
auto d( 1.41421f );
.
For more information, see Initializers and the code examples later in this document.
When auto
is used to declare the loop parameter in a range-based for
statement, it uses a different initialization syntax, for example for (auto& i : iterable) do_action(i);
. For more information, see Range-based for
Statement (C++).
The auto
keyword is a placeholder for a type, but it isn't itself a type. Therefore, the auto
keyword can't be used in casts or operators such as sizeof
and (for C++/CLI) typeid
.
Usefulness
The auto
keyword is a simple way to declare a variable that has a complicated type. For example, you can use auto
to declare a variable where the initialization expression involves 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 the variable yourself because the type of a lambda expression is known only to the compiler. For more information, see Examples of Lambda Expressions.
Trailing Return Types
You can use auto
, together with the decltype
type specifier, to help write template libraries. Use auto
and decltype
to declare a function template whose return type depends on the types of its template arguments. Or, use auto
and decltype
to declare a function template that wraps a call to another function, and then returns whatever is the return type of that other function. For more information, see decltype
.
References and cv-qualifiers
Using auto
drops references, const
qualifiers, and volatile
qualifiers. Consider the following example:
// cl.exe /analyze /EHsc /W4
#include <iostream>
using namespace std;
int main( )
{
int count = 10;
int& countRef = count;
auto myAuto = countRef;
countRef = 11;
cout << count << " ";
myAuto = 12;
cout << count << endl;
}
In the previous example, myAuto is an int
, not an int
reference, so the output is 11 11
, not 11 12
as would be the case if the reference qualifier hadn't been dropped by auto
.
Type deduction with braced initializers (C++14)
The following code example shows how to initialize an auto
variable using braces. Note the difference between B and C and between A and E.
#include <initializer_list>
int main()
{
// std::initializer_list<int>
auto A = { 1, 2 };
// std::initializer_list<int>
auto B = { 3 };
// int
auto C{ 4 };
// C3535: cannot deduce type for 'auto' from initializer list'
auto D = { 5, 6.7 };
// C3518 in a direct-list-initialization context the type for 'auto'
// can only be deduced from a single initializer expression
auto E{ 8, 9 };
return 0;
}
Restrictions and error messages
The following table lists the restrictions on the use of the auto
keyword, and the corresponding diagnostic error message that the compiler emits.
Error number | Description |
---|---|
C3530 | The auto keyword can't be combined with any other type-specifier. |
C3531 | A symbol that is declared with the auto keyword must have an initializer. |
C3532 | You incorrectly used the auto keyword to declare a type. For example, you declared a method return type or an array. |
C3533, C3539 | A parameter or template argument can't be declared with the auto keyword. |
C3535 | A method or template parameter can't be declared with the auto keyword. |
C3536 | A symbol can't be used before it's initialized. In practice, it means that a variable can't be used to initialize itself. |
C3537 | You can't cast to a type that is declared with the auto keyword. |
C3538 | All the symbols in a declarator list that is declared with the auto keyword must resolve to the same type. For more information, see Declarations and Definitions. |
C3540, C3541 | The sizeof and typeid operators can't be applied to a symbol that is declared with the auto keyword. |
Examples
These code fragments illustrate some of the ways in which the auto
keyword can be used.
The following declarations are equivalent. In the first statement, variable j
is declared to be type int
. In the second statement, variable k
is deduced to be type int
because the initialization expression (0) is an integer.
int j = 0; // Variable j is explicitly type int.
auto k = 0; // Variable k is implicitly type int because 0 is an integer.
The following declarations are equivalent, but the second declaration is simpler than the first. One of the most compelling reasons to use the auto
keyword is simplicity.
map<int,list<string>>::iterator i = m.begin();
auto i = m.begin();
The following code fragment declares the type of variables iter
and elem
when the for
and range for
loops start.
// cl /EHsc /nologo /W4
#include <deque>
using namespace std;
int main()
{
deque<double> dqDoubleData(10, 0.1);
for (auto iter = dqDoubleData.begin(); iter != dqDoubleData.end(); ++iter)
{ /* ... */ }
// prefer range-for loops with the following information in mind
// (this applies to any range-for with auto, not just deque)
for (auto elem : dqDoubleData) // COPIES elements, not much better than the previous examples
{ /* ... */ }
for (auto& elem : dqDoubleData) // observes and/or modifies elements IN-PLACE
{ /* ... */ }
for (const auto& elem : dqDoubleData) // observes elements IN-PLACE
{ /* ... */ }
}
The following code fragment uses the new
operator and pointer declaration to declare pointers.
double x = 12.34;
auto *y = new auto(x), **z = new auto(&x);
The next code fragment declares multiple symbols in each declaration statement. Notice that all of the symbols in each statement resolve to the same type.
auto x = 1, *y = &x, **z = &y; // Resolves to int.
auto a(2.01), *b (&a); // Resolves to double.
auto c = 'a', *d(&c); // Resolves to char.
auto m = 1, &n = m; // Resolves to int.
This code fragment uses the conditional operator (?:
) to declare variable x
as an integer that has a value of 200:
int v1 = 100, v2 = 200;
auto x = v1 > v2 ? v1 : v2;
The following code fragment initializes variable x
to type int
, variable y
to a reference to type const int
, and variable fp
to a pointer to a function that returns type int
.
int f(int x) { return x; }
int main()
{
auto x = f(0);
const auto& y = f(1);
int (*p)(int x);
p = f;
auto fp = p;
//...
}
See also
Keywords
/Zc:auto
(Deduce variable type)
sizeof
operator
typeid
operator new
Declarations and definitions
Examples of lambda expressions
Initializers
decltype