C ++ Когда нам лучше использовать static2cast с двумя цепочками, чем reinterpret_cast? - PullRequest
8 голосов
/ 06 июля 2011

Прежде всего, это не дубликат Почему у нас есть reinterpret_cast в C ++, когда два сцепленных static_cast могут выполнять свою работу? .

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

Ответы [ 6 ]

9 голосов
/ 06 июля 2011

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

reinterpret_cast означает «относиться к этим битам как ...». Статические приведения в цепочку не одинаковы, поскольку они могут изменять свои цели в соответствии срешетка наследования.

struct A {
    int x;
};

struct B {
    int y;
};

struct C : A, B {
    int z;
};

C c;
A * a = &c;

int main () {
    assert (reinterpret_cast <B *> (a) != static_cast <B *> (static_cast <C *> (a)));
}

Если вы не уверены на 100%, что a указывает на b, используйте dynamic_cast, который будет искать вышеуказанное решение (хотя и с затратами времени выполнения).Имейте в виду, что это может вернуть NULL или вызвать сбой.

Я пытаюсь вспомнить времена, когда я на самом деле использовал reinterpret_cast, на самом деле их только два:

  • когда функция архивирует / шифрует произвольный буфер, и я хочу использовать const char * для его обхода
  • if(*reinterpret_cast<uint32_t*>(array_of_4_bytes_A) < *reinterpret_cast<uint32_t*>(array_of_4_bytes_B) или что-то подобное.Строки, подобные этой, требуют проверки и требуют комментариев.

В противном случае, если у вас есть A*, который действительно B*, то вы, вероятно, захотите объединение.

5 голосов
/ 06 июля 2011

Я бы, например, скорее видел reinterpret_cast <TargetType> (pointer_of_some_other_type), чем static_cast <TargetType> (static_cast <void*> (pointer_of_some_other_type)) или static_cast <TargetType> ((void*) (pointer_of_some_other_type)) в любое время.Эта цепочка приведений, проходящих через void *, является просто хитрым, закулисным способом избежать использования страшного reinterpret_cast.

Многие проекты запрещают использование reinterpret_cast, если не предоставлен отказ;Человек, который написал код, должен оправдать использование актеров.IMO, цепочка статических приведений хуже (намного хуже!), Чем reinterpret_cast.Цепочка имеет те же эффекты, те же проблемы, что и reinterpret_cast, но ее не так легко найти с помощью grep.

Приложение
Посмотрите наэто так.Случай 1, вы используете reinterpret_cast, вы просматриваете все обручи проекта, чтобы оправдать его использование, менеджер проекта дает отказ.Спустя месяцы прослеживается ошибка при использовании вами dynamic_cast.У вас есть бесплатная карта.Это задница менеджера проекта, которая готова дать вам эту карту.

Случай 2, вы используете хитрую, закулисную цепочку статических приведений, и код проскальзывает через рецензирование невредимым.Несколько месяцев спустя прослеживается ошибка в использовании вами презренной техники.У вашего менеджера проекта могут быть проблемы с тем, чтобы не уловить эту злобу, но на кону ваша задница.У вас нет того выхода из тюрьмы без карты.Вы не пропустите Go.Вы идете прямо к линии безработицы.

2 голосов
/ 06 июля 2011

Поскольку перечисление сценариев может продолжаться очень долго, я выражаюсь простыми словами:

Если цепочка static_cast<> s не выдает ошибку компиляции, вам следует избегать reinterpret_cast<>.

2 голосов
/ 06 июля 2011

Всегда используйте реинтерпретацию приведения в качестве крайней меры - он не выполняет никакой проверки!- поэтому, если вы можете объединить два, три или десять операторов вместе, которые выполняют какую-то проверку операции, вы получили что-то стоящее.

1 голос
/ 06 июля 2011

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

0 голосов
/ 06 июля 2011

Потому что теоретически они могли бы делать что-то другое (хотя такой случай трудно представить).Что еще более важно, они посылают различные сигналы читателю и рассказывают другую историю компилятору (что может повлиять на оптимизацию).Логично, я бы сказал, использовать цепочку от static_cast до void* для случаев к / из типа символов (например, дамп изображения необработанной памяти), и других случаев, которые хорошо определены и переносимы, и reinterpret_cast, когда выВы выполняете очень низкоуровневую аппаратно-зависимую работу: извлекаете поле экспоненты из float, приводя его адрес к unsigned int*, и маскируя биты, например.

...