Разрешено ли отбрасывать константу для объекта, определенного константой, если он фактически не изменен?

Разрешено ли следующее:

const int const_array[] = { 42 };

int maybe_inc(bool write, int* array) {
  if (write) array[0]++;
  return array[0];
}

int main() {
  return maybe_inc(false, const_cast<int *>(const_array));
}

В частности, можно ли отбросить константу const_array, которая была определена как const, если объект фактически не изменен, как в примере?


person BeeOnRope    schedule 03.02.2019    source источник
comment
В самом деле, вы в безопасности до тех пор, пока на самом деле не выполняется запись. Сам const_cast не приводит к UB. См. Также (возможный дубликат?): stackoverflow.com/questions/29883327/   -  person Cody Gray    schedule 03.02.2019


Ответы (2)


да. Это совершенно законно. (Это опасно, но допустимо.) Если вы (пытаетесь) изменить объект, объявленный как const, поведение будет неопределенным.

Из n4659 (последний черновик C ++ 17), раздел 10.1.7.1 [dcl.type.cv] пункт 4:

За исключением того, что любой член класса, объявленный изменяемым (10.1.1), может быть изменен, любая попытка изменить константный объект во время его жизни (6.8) приводит к неопределенному поведению

Мой акцент. Это из C ++ 17, но это верно для всех версий C ++.

Если вы посмотрите раздел о const_cast, вы увидите, что

[Примечание: в зависимости от типа объекта операция записи через указатель, lvalue или указатель на член данных в результате const_cast, отбрасывающего const-qualifier76, может привести к неопределенному поведению (10.1.7.1). - конец примечания]

Примечания не являются нормативными, но это строго подразумевает, что получение неконстантной ссылки или указателя на константный объект является законным. Это запись недопустима.

person Martin Bonner supports Monica    schedule 03.02.2019
comment
Интересно, поэтому этот ответ неверен (или, по крайней мере, неточен), когда говорится, что вам не разрешено использовать переменные const_cast, которые на самом деле const. - фактическое ограничение заключается в том, что вам не разрешено изменять переменные, которые на самом деле являются константными (и, конечно, отбрасывание const удаляет ограждения, которые обычно предотвращали бы это)? - person BeeOnRope; 03.02.2019
comment
@BeeOnRope Ага. - person Martin Bonner supports Monica; 03.02.2019
comment
@BeeOnRope Подтверждаю, что эта цитата неверна и ваша интерпретация верна. - person Lightness Races in Orbit; 03.02.2019
comment
На самом деле удивительно, сколько неправильных ответов, получивших высокую оценку, можно найти на эту тему. Вот еще один. stackoverflow.com/questions/357600/is-const-cast-safe - person StoryTeller - Unslander Monica; 03.02.2019

Если он компилируется, то это разрешено. Но это не значит, что это законно.

#include <iostream>

int main(int argc, char *argv[]) 
{
    const int arr[] = {1, 2, 3};
    int* parr = const_cast<int*>(arr);
    parr[0] = 0;
    for(auto& n : arr)
        std::cout << n << std::endl;
}

Приведенный выше код компилируется в компиляторе Ubuntu 20.04 g++. Он также работает без проблем. Но приведенный выше код на самом деле является неопределенным поведением.

person eigenfield    schedule 13.08.2020