//
p2 = p3; //
//
Копирование объекта не изменяет копируемый объект. Поэтому несущественно, является ли копируемый или копирующий объект константой.
Спецификатор const нижнего уровня, напротив, никогда не игнорируется. При копировании объектов у них обоих должны быть одинаковые спецификаторы const нижнего уровня, или должно быть возможно преобразование между типами этих двух объектов. Как правило, преобразование неконстанты в константу возможно, но не наоборот.
int *p = p3; //
p2 = p3; //
p2 = &i //
int &r = ci; //
//
const int &r2 = i; //
У указателя p3 есть спецификатор const нижнего и верхнего уровня. При копировании указателя p3 можно проигнорировать его спецификатор const верхнего уровня, но не тот факт, что он указывает на константный тип. Следовательно, нельзя использовать указатель p3 для инициализации указателя p, который указывает на простой (неконстантный) тип int. С другой стороны, вполне можно присвоить указатель p3 указателю p2. У обоих указателей тот же тип (спецификатор const нижнего уровня). Тот факт, что p3 — константный указатель (т.е. у него есть спецификатор const верхнего уровня), не имеет значения.
Упражнение 2.30. Укажите по каждому из следующих объявлений, имеет ли объявляемый объект спецификатор const нижнего или верхнего уровня.
const int v2 = 0;
int v1 = v2;
int *p1 = &v1, &r1 = v1;
const int *p2 = &v2, *const p3 = &i, &r2 = v2;
Упражнение 2.31. С учетом объявлений в предыдущем упражнении укажите, допустимы ли следующие присвоения. Объясните, как спецификатор const верхнего или нижнего уровня применяется в каждом случае.
r1 = v2;
p1 = p2; р2 = p1;
p1 = p3; p2 = p3;
constexpr и константные выражения
Является ли данный объект (или выражение) константным выражением, зависит от типов и инициализаторов. Например:
const int max_files = 20; //
const int limit = max_files + 1; //
int staff_size = 27; //
const int sz = get_size(); //
Хотя переменная staff_size инициализируется литералом, это неконстантное выражение, поскольку он имеет обычный тип int, а не const int. С другой стороны, хоть переменная sz и константа, значение ее инициализатора неизвестно до времени выполнения. Следовательно, это неконстантное выражение.
constexprВ большой системе может быть трудно утверждать (наверняка), что инициализатор — константное выражение. Константная переменная могла бы быть определена с инициализатором, который мы полагаем константным выражением. Однако при использовании этой переменной в контексте, требующем константного выражения, может оказаться, что инициализатор не был константным выражением. Как правило, определение объекта и его использования в таком контексте располагаются довольно далеко друг от друга.
constexpr. constexpr неявно являются константой и должны инициализироваться константными выражениями.
constexpr int mf = 20; //