Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Использование const_cast для передачи константного аргумента данных функции, параметр которой не является константным [дубликатом]

Автор вопроса: user1099327Ответов: 2

Мы можем использовать const_cast для передачи константного аргумента данных функции, параметр которой не является константой.

int fun(int* ptr)
{
    return (*ptr + 10);
}
int main(void)
{
    int val = 10;
    const int *ptr = &val;
    int *ptr1 = const_cast <int *>(ptr);
    cout << fun(ptr1);
    return 0;
}
Output:
20

Но мы также можем добиться приведения следующим образом:

int fun(int* ptr)
{
    return (*ptr + 10);
}
int main(void)
{
    int val = 10;
    const int *ptr = &val;
    int *ptr1 = (int *)ptr;
    cout << fun(ptr1);
    return 0;
}

Выход: 20

Тогда какая необходимость в использовании const_cast в этом конкретном сценарии? Есть ли преимущество использования const_cast только в этом конкретном сценарии?

  • Помимо ясности и безопасности кода есть еще одно преимущество: его можно найти. Намного сложнее найти все места, где кто-то отбрасывает константность, используя приведения в стиле C. molbdnilo 30.01.2014
  • (int*) в этом случае совпадает с const_cast<int*>. Simple 30.01.2014

c++const-cast

Ответы

Ответ 1 · рейтинг 3 · user3159253

Потому что, когда вы указываете const_cast, вы явно указываете, что хотите удалить константность, в то время как приведение в старом стиле позволяет вам приводить что угодно к чему угодно. См. https://www.securecoding.cert.org/confluence/display/cplusplus/EXP05-CPP.+Do+not+use+C-style+casts

Ответ 2 · Mike Seymour

Злой актерский состав в стиле C сделает практически любое преобразование, которое отдаленно возможно. Используя это, вы теряете всякую надежду на то, что система типов отловит ошибки в вашем коде.

Приведения C++ ограничивают типы возможных преобразований, уменьшая вероятность случайного приведения к неправильному типу.

Например, это приведение будет скомпилировано, но даст какое-то неопределенное поведение, если вы попытаетесь использовать указатель:

double * bad = (double*)ptr;

в то время как это приведение не сможет скомпилироваться, так как const_cast не может выполнять преобразования типов:

double * less_bad = const_cast<double*>(ptr);

Приведения работают (более или менее) следующим образом:

  • static_cast позволяет отменить "безопасные" преобразования; например, преобразование указателя на базовый класс в указатель на производный класс или void* в типизированный указатель. Он не допускает преобразований, которые не имеют смысла в системе типов.
  • reinterpret_cast допускает более сложные преобразования, такие как преобразование указателей в целые числа или несвязанные типы указателей. Используйте его с осторожностью, если вам нужно отказаться от системы типов, чтобы сделать что-то необычное.
  • const_cast позволяет удалить квалификаторы const и volatile, но не разрешает преобразование типов.
  • dynamic_cast позволяет выполнять преобразование между указателями или ссылками на полиморфные типы с проверкой во время выполнения, что преобразование допустимо. Это единственное "безопасное" приведение, так как оно не может дать неверно напечатанный результат.
  • Злой состав C позволяет все, что могут делать static_cast, reinterpret_cast и const_cast, и даже больше. Синтаксис трудно обнаружить или найти, поэтому используйте его, если хотите скрыть истинный ужас своего кода и довести до безумия программистов, обслуживающих его.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы