//
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; //