Выбрать главу

Как и любой другой константный указатель, указатель constexpr может указать на константный или неконстантный тип.

constexpr int *np = nullptr; // np - нулевой константный указатель

                             // на int

int j = 0;

constexpr int i = 42;        // типом i является const int

// i и j должны быть определены вне любой функции

constexpr const int *p = &i; // p - константный указатель

                             // на const int i

constexpr int *p1 = &j;      // p1 - константный указатель на int j

Упражнения раздела 2.4.4

Упражнение 2.32. Допустим ли следующий код? Если нет, то как его исправить?

int null = 0, *p = null;

2.5. Работа с типами

По мере усложнения программ используемые в них типы также становятся все более сложными. Осложнения в использовании типов возникают по двум причинам. Имена некоторых типов трудно писать по памяти. Написание некоторых их форм утомительно и подвержено ошибкам. Кроме того, формат записи сложного типа способен скрыть его цель или значение. Другой источник осложнений кроется в том, что иногда трудно точно определить необходимый тип. Это может потребовать оглянуться на контекст программы.

2.5.1. Псевдонимы типов

Псевдоним типа (type alias) — это имя, являющееся синонимом имени другого типа. Псевдонимы типа позволяют упростить сложные определения типов, облегчая их использование. Псевдонимы типа позволяют также подчеркивать цель использования типа. Определить псевдоним типа можно одним из двух способов. Традиционно он определяется при помощи ключевого слова typedef:

typedef double wages;   // wages - синоним для double

typedef wages base, *p; // base - синоним для double, a p - для double*

Ключевое слово typedef может быть частью базового типа в объявлении (см. раздел 2.3). Объявления, включающие ключевое слово typedef, определяют псевдонимы типа, а не переменные. Как и в любое другое объявление, в это можно включать модификаторы типа, которые определяют составные типы, включающие базовый тип. 

Новый стандарт вводит второй способ определения псевдонима типа при помощи объявления псевдонима (alias declaration) и знака =.

using SI = Sales_item; // SI - синоним для Sales_item

Объявление псевдонима задает слева от оператора = имя псевдонима типа, который расположен справа.

Псевдоним типа — это имя типа, оно может присутствовать везде, где присутствует имя типа.

wages hourly, weekly; // то же, что и double hourly, weekly;

SI item;              // то же, что и Sales_item item

Указатели, константы и псевдонимы типа

Объявления, использующие псевдонимы типа, представляющие составные типы и константы, могут приводить к удивительным результатам. Например, следующие объявления используют тип pstring, который является псевдонимом для типа char*.

typedef char *pstring;

const pstring cstr = 0; // cstr - константный указатель на char

const pstring *ps;      // ps - указатель на константный указатель

                        // на тип char

Базовым типом в этих объявлениях является const pstring. Как обычно, модификатор const в базовом типе модифицирует данный тип. Тип pstring — это указатель на тип char, a const pstring — это константный указатель на тип char, но не указатель на тип const char.

Заманчиво, хоть и неправильно, интерпретировать объявление, которое использует псевдоним типа как концептуальную замену псевдонима, соответствующим ему типом:

const char *cstr = 0; // неправильная интерпретация const pstring cstr

Однако эта интерпретация неправильна. Когда используется тип pstring в объявлении, базовым типом объявления является тип указателя. При перезаписи объявления с использованием char*, базовым типом будет char, а * будет частью оператора объявления. В данном случае базовый тип — это const char. Перезапись объявляет cstr указателем на тип const char, а не константным указателем на тип char.