Спецификатор const верхнего и нижнего уровней

Задания раздела 2.4.3
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;
p1=p3;
p2=p1;
p2=p3;

p103_ex2-4-3

После прочтения и небольшого разбора предыдущей темы можно сходу понять, о чём написано в следующей.
Спецификатор const верхнего уровня - это такой, который используется для объявления указателя константой. int* const p=&i; (константный указатель)
Спецификатор const нижнего уровня - это такой, который указывает на константный объект. const int *p=&i; (указатель на константу)
Так же справедливо следующее - если объект сам константа, то const верхнего уровня. const int i=1024; - const верхнего уровня.
const int i=1024;
const int* p=&i; /* изменить p нельзя, но const нижнего уровня (потому что указатель на константный объект */
const int* const p1=p; // const слева нижнего уровня, справа - верхнего

Вот программа, которая наглядно демонстрирует const верхнего и нижнего уровней.
#include <iostream>
int main ()
{
int i=1024;
int *const p1=&i;
const int ci=42;
const int* p2=&ci;
const int* const p3=p2;
const int &r=ci; // const в ссылочных типах всегда нижнего уровня

i=ci; /* ничего такого, копируем значение константы в обычный неконстантый объект */
p2=p3; /* до и после присвоения p2 и p3 содержат адрес переменной ci, константным является только указатель p3, но его значение можно скопировать в неконстантый указатель, при этом const верхнего уровня p3 игнорируется */
std::cout << i << " " << ci << " " << p2 << " " << p3 << std::endl;
return(0);
}
Еще немного практики. Следует сказать, что спецификатор const нижнего уровня никогда не игнорируется, и если охота заиметь адрес указателя на константу, то только в другом указателе на константу (чтобы окончательно не сойти с ума, я так полагаю, при чтении чужого кода). Если использовать адрес указателя на константу в обычном указателе, то можно сгоряча попробовать изменить значение константного объекта, на который указывает указатель. А так видишь const - и всё, никакой самодеятельности.
В общем вот пример:

#include <iostream>
int main ()
{
int i=1024;
int *const p1=&i;
const int ci=42;
const int* p2=&ci;
const int* const p3=p2;
int* p=p3; /*недопустимо, потому что спецификатор const нижнего уровня игнорировать нельзя. Исправить можно написав const int* p=p3; */
p2=p3;
p2=&i;
int &r=ci; /* недопустимо, потому что ссылка на константу должна быть со спецификатором const нижнего уровня. const int &r=ci; */
int &r2=i;
std::cout << i << " " << ci << " " << p2 << " " << p3 << std::endl;
return(0);
}
Итак, прокачав скилл наблюдения за поведением указателей на константу в противоестественной среде, похоже я готов к заданиям.
2.30. Укажите по каждому из следующих объявлений, имеет ли объявляемый объект спецификатор const нижнего или верхнего уровня.
const int v2=0;
int v1=v2;
int* p1=&v1, &r1=v1;
const int *p2=&v2, *const p3=&i, &r2=v2;

const int v2=0; // const верхнего уровня, потому что сам объект - константа
int v1=v2; //просто копируем значение константного объекта
int* p1=&v1, &r1=v1; // обычный указатель p1 на v1, обычная ссылка r1 на v1;
const int *p2=&v2, /*const нижнего уровня, указатель на константу */ *const p3=&i, /* слева нижнего(указатель на константный объект), справа - верхнего уровней (сам указатель константа), но переменная i - не определена*/ &r2=v2; /*ссылка на константу всегда нижнего уровня */
2.31. С учетом объявлений в предыдущем упражнении укажите, допустимы ли следующие присвоения. Объясните, как спецификатор const верхнего или нижнего уровня применяется в каждом случае.
r1=v2;
p1=p2;
p1=p3;
p2=p1;
p2=p3;

Лень и экономия бумаги для заданий в моём понимании достойна всякого порицания. Я начинаю жалеть, что купил эту книжку. Авторы или локализаторы просто держат меня за идиота. Или может быть они знают, с чем мне придется столкнуться в будущем и просто готовят меня к этому. Например к отсутствию документации и комментариев к коду.

const int v2=0;
int v1=v2;
int* p1=&v1, &r1=v1;
const int *p2=&v2, *const p3=&i, &r2=v2;
r1=v2; //r1 - обычная ссылка на неконстантный объект. v1=v2;
p1=p2; // p1 обычный указатель, p2 - указатель на константный объект, а const в этом случае нижнего уровня, значит присвоение некорректно.
p1=p3; // p1 обычный указатель, а p3  - константный указатель на константный объект, имеет спецификаторы const верхнего и нижнего уровней. нижнего уровня спецификатор не игнорируется
p2=p1; // допустимо, потому что p2 - указатель на константный объект, но сам не является константным
p2=p3; // допустимо, константный указатель на константный объект присваивается указателю на константу. так как оба указателя имеют спецификаторы const нижнего уровня, то присвоение корректно, а спецификатор const верхнего уровня в данном случает игнорируется, потому что присваиваемый объект не изменяется.
Надеюсь что я не допустил слишком серьезных ошибок, потому что перечитывать всё это я пока что не в состоянии.


 

Добавить комментарий