Ссылаясь на 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 ……..
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
Ты не должен просто добавлять const
с reinterpret_cast
, reinterpret_cast
должно быть в первую очередь это: переосмысление указателя (или что-то еще).
Другими словами, если вы собираетесь из const char*
в char*
(надеюсь, потому что есть плохой API, который вы не можете изменить), затем const_cast
твой друг. Это действительно все, что должно быть.
Но если вам нужно идти от MyPODType*
в const char*
, тебе нужно reinterpret_cast
и это просто приятно, не требуя const_cast
на нем.
Есть одна вещь, которую нужно иметь в виду: вы не можете использовать 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
Единственное место, где я могу подумать о связывании reinterpret_cast с const-ness, — это передача объекта const в API, который принимает указатель void —
UINT ThreadFunction(void* param)
{
const MyClass* ptr = reinterpret_cast<const MyClass*>(param);
}
да, как вы знаете, const_cast означает, что он удаляет константность из определенного типа.
Но когда нам нужно добавить константу к типу. Есть ли причина, по которой мы должны это сделать?
например,
void PrintAnything(void* pData)
{
const CObject* pObject = reinterpret_cast<CObject*>(pData);
// below is bla-bla-bla.
}
reinterpret_cast не имеет ничего общего с «const».
const_cast означает две вещи.
первый — удалить константу из типа, а второй — дать явный код. Потому что вы можете использовать приведение, используя приведение в стиле C, но это не является явным, поэтому это не рекомендуется.
Они не функционируют одинаково. это определенно другое.