Использование const_cast для добавления константности — плохая идея?

как все мы знаем, использование const_cast для удаления константности указателя следует избегать.

Но как обстоят дела с этим?

Для моего случая использования у меня есть функция, которая копирует данные (байты) из неконстантного исходного буфера.
Я подумал, что хорошее дизайнерское решение — объявить параметр в соответствии с исходным буфером полностью постоянным.

void copyfunction(const char* const data) { ... }

Для вызова функции, как показано ниже, это приведет к ошибке типа указателя ‘const char * const <-> char * ‘.

void main() {
char sourcebuffer[] = {0x00};

copyfunction(sourcebuffer);
}

Конечно, теперь я мог бы просто объявить sourcebuffer как const, но в моем случае у меня нет доступа к этой переменной, потому что она находится в другом месте кода (внешняя библиотека).

void main() {
char sourcebuffer[] = {0x00};

copyfunction(const_cast<const char* const>(sourcebuffer));
}

Тем не менее, код за его пределами будет работать, но это хороший стиль (в соответствии с моим вариантом использования)?

Я думал, объявив параметр copyfunction as const гарантирует пользователю не изменять (только для чтения) указатель или местоположение самого исходного буфера.
Таким образом, в этом случае const_cast будет только необходимым злом, чтобы позволить вызов функции, а не преднамеренно удалять постоянство указателя …

поздравил

3

Решение

Вы не должны использовать const_cast добавить const, так как:

  1. это не нужно T* неявно преобразуется в const T*, Ваш вопрос гласит, что char sourcebuffer[] = {0x00}; copyfunction(sourcebuffer); это ошибка, но это не так.

  2. это потенциально (хотя и маловероятно) вредно. Может удалить volatile от типа указателя, который здесь не является намерением и приведет к неопределенному поведению, если sourcebuffer были объявлены как volatile sourcebuffer[],

5

Другие решения

Вы не должны использовать const_cast добавить const так как

  1. В случаях, когда операция безопасна, это почти всегда не требуется. int* превращается в const int* неявно.

  2. Он может делать что-то, чего вы не хотите. Может раздеться volatileили заставит вас упустить тот факт, что const был добавлен где-то еще в ваших переменных и ваших const_cast теперь молча их раздевает.

  3. В тех случаях, когда требуется добавить constЕго использование опасно в рассуждениях.

Есть случаи, когда нужно позвонить const_cast чтобы добавить const это не произойдет неявно.

void assign_ptr( int const*& lhs, int const* rhs ) { lhs = rhs; }
int const foo = 7;
int* bar = nullptr;
assign_ptr( const_cast<int const*&>(bar), &foo );
*bar = 2; // undefined behavior!
std::cout << foo << "@" << &foo << "\n"; // will print probably 7@something
std::cout << *bar << "@" << bar << "\n"; // will print probably 2@same address as above!

вышеуказанный призыв к assign_ptr только добавляет const, но это не произойдет неявно.

Побочным эффектом является то, что модификация *bar является неопределенным поведением, так как оно изменяет объявленную переменную const (это делает bar, int*, указывать на foo const int).

Так что пока const_cast требуется сделать assign_ptr вызов компиляции, потому что это было небезопасно. const_cast не делает его более безопасным, он просто скрывает ошибку.

Это частный случай проблемы прямоугольника. Квадраты не являются прямоугольниками, потому что если вы измените ширину квадрата, его высота также изменится, и этого не произойдет, если вы измените прямоугольник. Так же, int** не int const**, (Обратите внимание, что неизменяемые квадраты являются своего рода неизменяемым прямоугольником; именно мутация вызывает проблему. В случае указателей int*const* это int const*const*: изменчивость указателей «более высокого уровня» вызывает проблему.)

5

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector