const_cast против reinterpret_cast

Ссылаясь на SO C ++ FAQ Когда следует использовать static_cast, dynamic_cast и reinterpret_cast?.

const_cast используется для удаления или добавления const в переменную и является единственным надежным, определенным и допустимым способом удаления constness.
reinterpret_cast используется для изменения интерпретации типа.

Я разумно понимаю, почему константную переменную следует приводить к неконстантной только с помощью const_cast, но я не могу найти разумное обоснование проблем, используя reinterpret_cast вместо const_cast для добавления constness.

Я понимаю, что использование reinterpret_cast даже для добавления константности не является нормой, но будет ли это UB или потенциальной бомбой замедленного действия для использования reinterpret_cast для добавления константности?

Причина, по которой я был смущен, заключается в том, что

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

Так что, если я добавлю constness с помощью reinterpret_cast и если вы reinterpret_cast вернете результат обратно к исходному типу, он должен вернуться к исходному типу и не должен быть UB, но это нарушает тот факт, что для удаления constness следует использовать только const_cast

На отдельном примечании стандарт гарантирует, что Вы можете добавить Constness, используя случайную интерпретацию

5.2.10. Переинтерпретация приведения (7) …… Когда значение v указателя типа «указатель на T1» преобразуется в тип «указатель на cv T2», результат
static_cast (static_cast (v)), если оба T1 и T2
Типы стандартного макета (3.9) и требования выравнивания T2
не более строгие, чем у T1 ……..

7

Решение

reinterpret_cast изменяет интерпретацию данных внутри объекта. const_cast добавляет или удаляет const Классификатор. Представление данных и константность являются ортогональными. Поэтому имеет смысл использовать разные ключевые слова.

Так что, если я добавлю constness с помощью reinterpret_cast и если вы reinterpret_cast вернете результат обратно к исходному типу, он должен вернуться к исходному типу и не должен быть UB, но это нарушает тот факт, что для удаления constness следует использовать только const_cast

Это даже не скомпилируется:

int * n = new int;
const * const_added = reinterpret_cast<const int *>(n);
int * original_type = reinterpret_cast<int*>(const_added);
// error: reinterpret_cast from type ‘const int*’ to type ‘int*’ casts away qualifiers
10

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

Ты не должен просто добавлять const с reinterpret_cast, reinterpret_cast должно быть в первую очередь это: переосмысление указателя (или что-то еще).

Другими словами, если вы собираетесь из const char* в char* (надеюсь, потому что есть плохой API, который вы не можете изменить), затем const_cast твой друг. Это действительно все, что должно быть.

Но если вам нужно идти от MyPODType* в const char*, тебе нужно reinterpret_castи это просто приятно, не требуя const_cast на нем.

4

Есть одна вещь, которую нужно иметь в виду: вы не можете использовать const_cast сделать const переменная для записи. Вы можете использовать его только для извлечения неконстантной ссылки из константной ссылки, если эта константная ссылка ссылается на неконстантный объект. Звучит сложно? Пример:

// valid:
int x;
int const& x1 = x;
const_cast<int&>(x1) = 0;
// invalid:
int const y = 42;
int const& y1 = y;
const_cast<int&>(y1) = 0;

На самом деле, оба из них будут компилироваться, а иногда даже «работать». Однако второй вызывает неопределенное поведение и во многих случаях завершает программу, когда постоянный объект помещается в постоянную память.

Тем не менее, еще несколько вещей: reinterpret_cast это самый мощный состав, но также и самый опасный, так что не используйте его, если это не нужно. Когда вам нужно идти от void* в sometype*использовать static_cast, Если вы идете в противоположном направлении, используйте встроенное неявное преобразование или явное static_cast, тоже. Аналогично с добавлением или удалением const, который также добавлен неявно. Что касается reinterpret_castсм. также обсуждение на C ++ Когда нам лучше использовать static2cast с двумя цепочками, чем reinterpret_cast? где обсуждается альтернатива, которая менее хакерская.

Uli

1

Единственное место, где я могу подумать о связывании reinterpret_cast с const-ness, — это передача объекта const в API, который принимает указатель void —

UINT ThreadFunction(void* param)
{
const MyClass* ptr = reinterpret_cast<const MyClass*>(param);
}
0

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

Но когда нам нужно добавить константу к типу. Есть ли причина, по которой мы должны это сделать?

например,

void PrintAnything(void* pData)
{
const CObject* pObject = reinterpret_cast<CObject*>(pData);
// below is bla-bla-bla.
}

reinterpret_cast не имеет ничего общего с «const».

const_cast означает две вещи.
первый — удалить константу из типа, а второй — дать явный код. Потому что вы можете использовать приведение, используя приведение в стиле C, но это не является явным, поэтому это не рекомендуется.

Они не функционируют одинаково. это определенно другое.

0
По вопросам рекламы [email protected]