2.5.2. Спецификатор типа auto
Нет ничего необычного в желании сохранить значение выражения в переменной. Чтобы объявить переменную, нужно знать тип этого выражения. Когда мы пишем программу, может быть на удивление трудно (а иногда даже невозможно) определить тип выражения. По новому стандарту можно позволить компилятору самому выяснять этот тип. Для этого используется спецификатор типа auto. В отличие от таких спецификаторов типа, как double, задающих определенный тип, спецификатор auto приказывает компилятору вывести тип из инициализатора. Само собой разумеется, у переменной, использующей спецификатор типа auto, должен быть инициализатор.
// тип item выводится из типа результата суммы val1 и val2
auto item = val1 + val2; // item инициализируется результатом val1 + val2
Здесь компилятор выведет тип переменной item из типа значения, возвращенного при применении оператора + к переменным val1 и val2. Если переменные val1 и val2 — объекты класса Sales_item (см. раздел 1.5), типом переменной item будет класс Sales_item. Если эти переменные имеют тип double, то у переменной item будет тип double и т.д.
Подобно любому другому спецификатору типа, используя спецификатор auto, можно определить несколько переменных. Поскольку объявление может задействовать только один базовый тип, у инициализаторов всех переменных в объявлении должны быть типы, совместимые друг с другом.
auto i = 0, *p = &i; // ok: i - int, а p - указатель на int
auto sz = 0, pi = 3.14; // ошибка: несовместимые типы у sz и pi
Составные типы, const и auto
Выводимый компилятором тип для спецификатора auto не всегда точно совпадает с типом инициализатора. Компилятор корректирует тип так, чтобы он соответствовал обычным правилам инициализации.
Во-первых, как уже упоминалось, при использовании ссылки в действительности используется объект, на который она ссылается. В частности, при использовании ссылки как инициализатора им является соответствующий объект. Компилятор использует тип этого объекта для выведения типа auto.
int i = 0, &r = i;
auto a = r; // a - int (r - псевдоним для i, имеющий тип int)
Во-вторых, выведение типа auto обычно игнорирует спецификаторы const верхнего уровня (см. раздел 2.4.3). Как обычно в инициализациях, спецификаторы const нижнего уровня учитываются в случае, когда инициализатор является указателем на константу.
const int ci = i, &cr = ci;
auto b = ci; // b - int (const верхнего уровня в ci отброшен)
auto с = cr; // с - int (cr - псевдоним для ci с const верхнего
// уровня)
auto d = &i; // d - int* (& объекта int - int*)
auto e = &ci; // e - const int* (& константного объекта - const нижнего
// уровня)
Если необходимо, чтобы у выведенного типа был спецификатор const верхнего уровня, его следует указать явно.
const auto f = ci; // выведенный тип ci - int; тип f - const int
Можно также указать, что необходима ссылка на автоматически выведенный тип. Обычные правила инициализации все еще применимы.
auto &g = ci; // g - const int&, связанный с ci
auto &h = 42; // ошибка: нельзя связать простую ссылку с литералом
const auto &j = 42; // ok: константную ссылку с литералом связать можно
Когда запрашивается ссылка на автоматически выведенный тип, спецификаторы const верхнего уровня в инициализаторе не игнорируются. Как обычно при связывании ссылки с инициализатором, спецификаторы const не относятся к верхнему уровню.
При определении нескольких переменных в том же операторе важно не забывать, что ссылка или указатель — это часть специфического оператора объявления, а не часть базового типа объявления. Как обычно, инициализаторы должны быть совместимы с автоматически выведенными типами:
auto k = ci, &l = i; // k - int; l - int&
auto &m = ci, *p = &ci; // m - const int&; p - указатель на const int
// ошибка: выведение типа из i - int;
// тип, выведенный из &ci - const int
auto &n = i, *p2 = &ci;
Упражнения раздела 2.5.2
Упражнение 2.33. С учетом определения переменных из этого раздела укажите то, что происходит в каждом из этих присвоений.
а = 42; b = 42; с = 42;
d = 42; е = 42; g = 42;
Упражнение 2.34. Напишите программу, содержащую переменные и присвоения из предыдущего упражнения. Выведите значения переменных до и после присвоений, чтобы проверить правильность предположений в предыдущем упражнении. Если они неправильны, изучите примеры еще раз и выясните, что привело к неправильному заключению.
Упражнение 2.35. Укажите типы, выведенные в каждом из следующих определений. Затем напишите программу, чтобы убедиться в своей правоте.
const int i = 42;
auto j = i; const auto &k = i; auto *p = &i;
const auto j2 = i, &k2 = i;
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОК