Ключом здесь является «объект, определенный с определением типа const». Важно то, как вы определяете (IOW, «выделяете память») объект, на который указывает. Если «объект» не был «создан» как const
, то не имеет значения, сколько константных или неконстантных указателей и ссылок вы используете - вы все равно можете изменить его.
Итак,
const int i = 0;
int *p = (int*)&i;
*p = 1;
- это UB.
Пока
int i = 0;
const int *cp = &i;
int *p = (int*) cp;
*p = 1;
в порядке.
Я подозреваю, что это будет работать даже с new
:
const int *cp = new const int(0);
int *p = (int*) cp;
*p = 1;
технически UB.
Он компилирует без предупреждения на cpp.sh, но это мало что значит.
Обновление: как указал Кристиан Гиббонс, язык в вопросе - C, поэтому часть об операторе new
не применяется. malloc()
а друзья никогда не const
.
Чтобы немного это расширить - одна из возможных причин написания стандарта таким образом - дать компилятору свободу использовать постоянную память для значений const. В этом случае запись в такие места становится аварийной или нет. Другими словами, UB.