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

Добавлено 16 мая 2021 в 13:57

Рассмотрим следующую инструкцию:

double d{ 5.0 };

Если C++ уже знает, что 5.0 – это литерал типа double, почему мы должны явно указывать, что d действительно является double? Разве не было бы неплохо, если бы мы могли сказать переменной, просто принимать правильный тип на основе значения, которым мы ее инициализируем?

Вывод типа для инициализированных переменных

При инициализации переменной вместо типа можно использовать ключевое слово auto, чтобы сообщить компилятору, что тип переменной должен выводиться из типа инициализатора. Это называется выводом типа (или англоязычные термины type inference и type deduction).

Например:

auto d{ 5.0 };   // 5.0 - это литерал типа double, поэтому d будет иметь тип double
auto i{ 1 + 2 }; // 1 + 2 вычисляется как int, поэтому i будет типа int

Это также работает со значениями, возвращаемыми из функций:

int add(int x, int y)
{
    return x + y;
}
 
int main()
{
    auto sum { add(5, 6) }; // add() возвращает int, поэтому тип sum будет выведен как int
    return 0;
}

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

Вывод типа для функций

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

auto add(int x, int y)
{
    return x + y;
}

Поскольку x + y вычисляется как int, компилятор определит, что эта функция должна иметь тип возвращаемого значения int. При использовании возвращаемого типа auto все инструкции return должны возвращать один и тот же тип, в противном случае возникнет ошибка.

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

Лучшая практика


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

Заинтересованные читатели могут задаться вопросом, почему использование auto при инициализации переменных нормально, но не рекомендуется для типов, возвращаемых функциями. Хорошее практическое правило состоит в том, что auto можно использовать при определении переменной, потому что объект, из которого переменная выводит тип, виден в правой части оператора. Однако с функциями дело обстоит иначе – нет контекста, который помог бы указать, какой тип возвращает функция. Пользователю фактически придется копаться в теле самой функции, чтобы определить, какой тип она возвращает. Это гораздо менее интуитивно понятно и, следовательно, более подвержено ошибкам.

Синтаксис, завершающийся возвращаемым типом

Ключевое слово auto также может использоваться для объявления функций с использованием синтаксиса, завершающегося возвращаемым значением (trailing return syntax), где тип возвращаемого значения указывается после остальной части прототипа функции.

Рассмотрим следующую функцию:

int add(int x, int y)
{
  return (x + y);
}

Используя auto, его можно было бы записать как:

auto add(int x, int y) -> int
{
  return (x + y);
}

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

Зачем вам это нужно?

Приятно, когда все имена функций выстраиваются в одну линию:

auto add(int x, int y) -> int;
auto divide(double x, double y) -> double;
auto printSomething() -> void;
auto generateSubstring(const std::string &s, int start, int len) -> std::string;

На данный момент мы рекомендуем продолжать использовать традиционный синтаксис возвращаемого значения функции. Но мы снова увидим этот синтаксис, завершающийся типом возвращаемого значения, в уроке «10.15 – Введение в лямбды (анонимные функции)».

Вывод типа для типов параметров функции

Многие начинающие программисты пробуют писать что-то вроде этого:

#include <iostream>
 
void addAndPrint(auto x, auto y) // действует только начиная с C++20
{
    std::cout << x + y;
}
 
int main()
{
    addAndPrint(2, 3);     // int
    addAndPrint(4.5, 6.7); // double
}

До C++20 это не работало, потому что во время компиляции компилятор не мог определить типы для параметров функции x и y. До C++20: если вы хотели создать универсальные функции, которые работают с множеством различных типов, вам следовало использовать шаблоны функций (описанные в следующей главе), а не вывод типов.

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

Для продвинутых читателей


Лямбда-выражения поддерживают автоматические параметры, начиная с C++14. Лямбда-выражения мы рассмотрим в будущих уроках.

Теги

autoC++ / CppLearnCppВывод типа / Type inferenceДля начинающихОбучениеПрограммированиеСинтаксис, завершающийся возвращаемым типом / Trailing return syntax

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.