Разрешено ли использование 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:

  1. Это может привести к трудностям поиска ошибок
  2. Вы выбрасываете const-соглашение с компилятором
  3. По сути, вы превращаете язык в язык более низкого уровня.

Да, вы можете сделать это. Нет, это не неопределенное поведение, если функция действительно не пытается записать в массив.

С помощью const_cast на объекте, который изначально определен как const это UB, поэтому неопределенное поведение возникает сразу в точке, которую вы называете const_cast,

Другие вопросы по тегам