Поделиться через


Ключевое слово auto (выведение типа)

Выводит тип объявленной переменной из выражения инициализации.

auto declarator initializer;

Заметки

Ключевое слово auto указывает компилятору использовать выражение инициализации объявленной переменной, чтобы вывести ее тип.

Ключевое слово auto рекомендуется использовать в большинстве ситуаций (кроме тех, когда требуется преобразование), поскольку оно обладает рядом преимуществ:

  • Надежность. Если тип выражения изменился (в том числе если изменен возвращаемый тип функции), это не влияет на его работу.

  • Эффективность. Преобразование гарантированно не будет выполнено.

  • Удобство использования. Можно не беспокоиться об опечатках и ошибках.

  • Эффективность. Быстрое написание кода.

Случаи преобразования, для которых не подходит ключевое слово auto:

  • Если необходимо получить конкретный тип.

  • Вспомогательные типы шаблона выражения (например, (valarray+valarray) или списки инициализаторов), хотя и в редких случаях, если вы намереваетесь написать строку кода auto x = { 1 }; и ожидаете получить значение типа int.

Чтобы использовать ключевое слово auto, укажите его вместо типа для определения переменной, а затем задайте выражение инициализации. Кроме того, ключевое слово auto можно изменить с помощью спецификаторов и деклараторов, например const, volatile, указателя (*), ссылки (&) и ссылки rvalue (&&). Компилятор вычисляет выражение инициализации, а затем использует эти сведения, чтобы вывести тип переменной.

Выражение инициализации может представлять собой присваивание (синтаксис со знаком равенства), прямую инициализацию (синтаксис в стиле функции), выражение operator new. Кроме того, выражение инициализации может представлять собой параметр for-range-declaration в выражении Основанное на диапазоне выражение for (C++). Дополнительные сведения см. в разделе Инициализаторы, а также в примерах кода в этом документе.

Ключевое слово auto является местозаполнителем для типа, однако само по себе не означает тип. Таким образом, ключевое слово auto не может использоваться в приведениях типов или в таких операторах, как sizeof и typeid.

Удобство

Ключевое слово auto — это простой способ объявить переменную, которая имеет сложный тип. Например, с помощью auto можно объявить переменную, в которой выражение инициализации содержит шаблоны, указатели на функции или указатели на члены.

Кроме того, с помощью auto можно объявить и инициализировать переменную в лямбда-выражение. Вы не сможете самостоятельно объявить тип переменной, поскольку тип лямбда-выражения известен только компилятору. Дополнительные сведения см. в разделе Примеры лямбда-выражений.

Отслеживание возвращаемых типов

Ключевое слово auto и спецификатор decltype помогают в написании библиотек шаблонов. Используйте auto и decltype для объявления функции шаблонов, возвращаемый тип которой зависит от типов аргументов его шаблонов. Кроме того, при помощи auto и decltype можно объявить шаблонную функцию, которая создает оболочку для вызова другой функции, а потом возвращает полученный результат, какой бы возвращаемый тип ни имела вторая функция. Дополнительные сведения см. в разделе Спецификатор типа decltype.

Ссылки и cv-квалификаторы

Обратите внимание, что использование auto удаляет ссылки, квалификаторы const и квалификаторы volatile. Рассмотрим следующий пример.

// 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;
}

Вы полагаете, что myAuto представляет собой ссылку на тип int, однако на самом деле это не так. На самом деле myAuto является объектом типа int, поэтому программа выводит 11 11, а не 11 12, как было бы в том случае, если бы ссылка не была удалена при добавлении ключевого слова auto.

Ограничения и сообщения об ошибках

В приведенной ниже таблице перечислены ограничения на использование ключевого слова auto и соответствующие диагностические сообщения об ошибках, которые выводит компилятор.

Номер ошибки

Описание

C3530

Ключевое слово auto не может использоваться в сочетании с другим спецификатором типа.

C3531

Символ, объявленный с помощью ключевого слова auto, должен иметь инициализатор.

C3532

Неверно используется ключевое слово auto для объявления типа. Например, был объявлен тип возвращаемого значения метода или массив.

C3533, C3539

Аргумент параметра или шаблона не может объявляться с помощью ключевого слова auto.

C3534

Символ, объявленный с помощью ключевого слова auto в выражении с оператором new, должен иметь инициализатор. Дополнительные сведения см. в разделе operator new (<new>).

C3535

Параметр метода или шаблона не может объявляться с помощью ключевого слова auto.

C3536

Символ не может быть использован до инициализации. Практически это означает, что переменную нельзя использовать для инициализации самой себя.

C3537

Выполнить приведение к типу, объявленному с помощью ключевого слова auto, невозможно.

C3538

Все символы в списке деклараторов, объявленные при помощи ключевого слова auto, должны разрешаться к одному и тому же типу. Дополнительные сведения см. в разделе Объявления.

C3540, C3541

Операторы sizeof и typeid не могут быть применены к символам, объявленным с помощью ключевого слова auto.

Примеры

В следующих фрагментах кода показаны ситуации, в которых может использоваться ключевое слово auto.

Следующие объявления эквивалентны. В первом операторе переменная j объявлена с типом int. Во втором операторе выводится, что переменная k имеет тип int, поскольку выражение инициализации (0) является целым числом.

   int j = 0;  // Variable j is explicitly type int.
   auto k = 0; // Variable k is implicitly type int because 0 is an integer.

Следующие объявления эквивалентны, но второе объявление проще первого. Одной из важнейших причин, по которым следует использовать ключевое слово auto, является простота.

   map<int,list<string>>::iterator i = m.begin(); 
   auto i = m.begin(); 

В следующем фрагменте кода тип переменных iter и elem объявляется при запуске цикла for и диапазона for.

// 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
    { /* ... */ }
}

В следующем примере кода объявляется указатель. Для этого используется оператор new и объявление указателя.

   double x = 12.34;
   auto *y = new auto(x), **z = new auto(&x);

В следующем примере кода объявлено несколько символов в каждом операторе объявления. Обратите внимание, что все символы во всех операторах разрешаются к одному и тому же типу.

   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.

В этом примере кода используется условный оператор (?:). Переменная x здесь объявляется как целочисленная переменная со значением 200.

   int v1 = 100, v2 = 200;
   auto x = v1 > v2 ? v1 : v2;

В следующем примере кода переменная x инициализируется как тип int, переменная y — как ссылка на тип const int, а переменная fp — как указатель на функцию, которая возвращает тип 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;
    //...
}

См. также

Ссылки

Ключевое слово auto

Спецификаторы классов хранения

Ключевые слова в C++

/Zc:auto (выведение типа переменной)

Оператор sizeof

typeid

operator new (<new>)

Объявления

Примеры лямбда-выражений

Инициализаторы

Спецификатор типа decltype