Разрешено ли использование const_cast для доступа только для чтения к объекту const?
В C++ у меня есть функция, которая требует только доступ только для чтения к массиву, но ошибочно объявлена как получение неконстантного указателя:
size_t countZeroes( int* array, size_t count )
{
size_t result = 0;
for( size_t i = 0; i < count; i++ ) {
if( array[i] == 0 ) {
++result;
}
}
return result;
}
и мне нужно вызвать его для массива const:
static const int Array[] = { 10, 20, 0, 2};
countZeroes( const_cast<int*>( Array ), sizeof( Array ) / sizeof( Array[0] ) );
это будет неопределенным поведением? Если так - когда программа попадет в UB - при выполнении const_cast и вызове функции или при доступе к массиву?
5 ответов
Да, это разрешено (если опасно!). Это фактическая запись в const
объект с неопределенным поведением, а не само приведение (7.1.5.1/4 [dcl.type.cv]).
Как отмечается в стандарте в 5.2.11/7 [expr.const.cast], в зависимости от типа объекта попытка записи через указатель является результатом отбрасывания. const
может привести к неопределенному поведению.
Поскольку ваш код не изменяет массив, и вы сказали компилятору, что вы знаете, что делаете, используя const_cast
, вы действительно будете в порядке. Тем не менее, я считаю, что вы технически вызываете неопределенное поведение. Лучше всего исправить объявление функции или написать, объявить и использовать его const-safe версию.
Проблема const_cast
всегда один и тот же - он позволяет вам "нарушать правила", так же как приведение к void*
- Конечно, вы можете сделать это, но вопрос в том, почему вы должны?
В этом случае это конечно хорошо, но вы должны спросить себя, почему вы не заявили size_t countZeroes( const int* array, size_t count )
на первом месте?
И как общее правило о const_cast
:
- Это может привести к трудностям поиска ошибок
- Вы выбрасываете const-соглашение с компилятором
- По сути, вы превращаете язык в язык более низкого уровня.
Да, вы можете сделать это. Нет, это не неопределенное поведение, если функция действительно не пытается записать в массив.
С помощью const_cast
на объекте, который изначально определен как const
это UB, поэтому неопределенное поведение возникает сразу в точке, которую вы называете const_cast
,