>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.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;
>decltype
>decltype
, возвращающий тип его операнда. Компилятор анализирует выражение и определяет его тип, но не вычисляет его результат.
>decltype(f()) sum = x; // sum имеет тот тип,
> // который возвращает функция f
Здесь компилятор не вызывает функцию >f()
, но он использует тип, который возвратил бы такой вызов для переменной >sum
. Таким образом, компилятор назначает переменной >sum
тот же тип, который был бы возвращен при вызове функции >f()
.
Таким образом, спецификатор >decltype
учитывает спецификатор >const