А.7. Автоматическое выведение типа переменной
С++ — статически типизированный язык: тип любой переменной известен на этапе компиляции. Более того, программист обязан указать тип каждой переменной. В некоторых случаях имена оказываются очень громоздкими, например:
std::map<std::string, std::unique_ptr<some_data>> m;
std::map<std::string, std::unique_ptr<some_data>>::iterator
iter = m.find("my key");
Традиционно для решения этой проблемы использовались псевдонимы типов (typedef), позволяющие сократить длину идентификатора типа и избавиться от потенциальных проблем несовместимости типов. Этот способ работает и в C++11, но появился и новый: если переменная инициализируется в объявлении, то в качестве ее типа можно указать auto. Тогда компилятор автоматически выведет тип переменной из типа инициализатора. Следовательно, приведенный выше пример итератора можно записать и так:
auto iter = m.find("my key");
Спецификатор auto необязательно употреблять изолированно; его можно использовать в сочетании с другими спецификаторами для объявления const-переменных, а также указателей и ссылок. Вот несколько примеров объявления переменных с помощью auto и дополнительных конструкций:
auto i = 42; // int
auto& j = i; // int&
auto const k = i; // int const
auto* const p = &i; // int * const
Правила выведения типа переменной основаны на правилах, применяемых в другом месте языка, где выводятся типы: параметры шаблонов функций. В объявлении вида
Какое-то-типовое-выражение-включающее-auto
var = some-expression;
переменная var имеет тот же тип, который был бы выведен, если бы она встречалась в качестве параметра шаблона функции, объявленного с таким же типовым выражением, только auto заменяется именем типового параметра шаблона:
template<typename T>
void f(type-expression var);
f(some-expression);
Это означает, что тип массива сводится к указателю, а ссылки опускаются, если только в типовом выражении переменная явно не объявлена как ссылка. Например:
int some_array[45];
auto p = some_array; // int*
int& r = *p;
auto x = r; // int
auto& y = r; // int&
Это позволяет существенно упростить объявление переменных, особенно в случаях, когда полный идентификатор типа очень длинный или даже неизвестен (например, тип результата вызова функции в шаблоне).