Является ли reinterpret cast единственным допустимым использованием reinterpret cast?
Недавно я узнал, что стандарт C++ содержит "строгие правила псевдонимирования", которые запрещают ссылаться на одно и то же место памяти через переменные разных типов.
Однако стандарт позволяет типам char
юридически псевдонимировать любой другой тип. Означает ли это, что reinterpret_cast
может по закону использоваться только для приведения к типу char *
или char &
?
Я считаю, что строгое алиасирование позволяет выполнять приведение между типами в иерархии наследования, но я думаю, что эти ситуации будут иметь тенденцию использовать dynamic_cast?
Спасибо
3 ответа:
Есть много различных применений
reinterpret_cast
. На страницеcppreference перечислены 11 различных случаев.Я думаю, что вы спрашиваете только о случаях 5 и 6: приведение
T *
кU *
и приведениеT
кU &
.В этих случаях актерский состав является законным до тех пор, пока нет нарушения выравнивания. Проблема строгого сглаживания возникает только при чтении или записи через результирующее выражение.
Ваше краткое изложение правила строгого сглаживания в вашем первом абзаце является отличным чрезмерное упрощение, в целом существует несколько юридических типов для
U
. На той же странице cppreference приведен маркированный список случаев; вы можете прочитать точный текст правила в стандартном проекте C++.
Можно также использовать reinterpret_cast для приведения типа указателя к целочисленному типу:
Конкретное целочисленное значение, которое вы получаете обратно, не переносится между платформами, но это безопасная и четко определенная операция.char* ptr = /* ... */ uintptr_t ptrInt = reinterpret_cast<uintptr_t>(ptr);
Есть и другие полезные применения
reinterpret_cast
.Указатель на целочисленный тип
Да, когда-то over хотел бы хранить значение указателя в целочисленном типе.
Единственный способ сделать это с приведениями в стиле C++ - это
reinterpret_cast
.Пример:
auto pointerValue = reinterpret_cast<std::uintptr_t>(pointer);
Хранение объектов в блоке необработанной памяти
Иногда вы хотите сохранить данные в стеке, но инициализировать его позже. Использование динамических распределений и указателей не будет использовать стек.
std::aligned_storage
делает большую работу, как необработанный, выровненный блок памяти.Я уверен, что есть много других применений, которые я не знаю, но это то, которое я уже использовал.struct MyStruct { int n; std::string s; }; // allocated on automatic storage std::aligned_storage<sizeof(MyStruct), alignof(MyStruct)>::type storage; // actually initialize the object new (&storage) MyStruct; // using the object reinterpret_cast<MyStruct*>(&storage)->n = 42;