Step 5 (S-10622)

From Stepik Wiki
Jump to: navigation, search

Step on Stepik: https://stepik.org/lesson/549/step/5

Очень внимательные слушатели могли заметить, что на предыдущем слайде я допустил ошибку. Если Вы не заметили, но считаете, что хорошо знаете C++, то не читайте дальше, а попробуйте сначала найти её и объяснить, почему это ошибка.

Ошибка заключается следующем присваивании: int const ** p1 = &p;  В данной строчке я ожидаю, что значение типа int ** (адрес переменной p) приведётся к значению типа int const **.

Если Вы попробуете скомпилировать этот код, то увидите, что он приводит к ошибке компиляции. Почему? Потому, что стандарт запрещает такие преобразования. Говоря точнее, стандартом разрешены (неявные) преобразования от T * к T const *, но не T ** к T const **.

Почему бы не разрешить такие преобразования?

Оказывается, что, если бы такие преобразования были разрешены, то можно было бы изменить константные данные. Другими словами, система константности C++ была бы некорректна — она позволяла бы изменять неизменяемые данные.

Вопрос: как с помощью преобразования вида T ** к T const ** можно было бы изменить константные данные (если бы C++ позволял такие преобразования)?

Попытайтесь сначала сами найти ответ на этот вопрос. Получилось? Вот как это можно сделать:

int const i = 1;int * p = 0;// p = &i;  не скомпилируется,  т.к. это преобразование int const * -> int *// В этой строке происходит запрещённое преобразование int ** -> int const **int const ** pp = &p;  // теперь *pp указывает на переменную p// следующая строка скомпилируется, т.к. *pp имеет тип int const**pp = &i; // это соответствует p = &i;*p = 2; // изменяем значение переменной i