Должен ли я использовать static_cast или reinterpret_cast при приведении void * к чему-либо - PullRequest
170 голосов
/ 22 ноября 2008

Кажется, что static_cast и reinterpret_cast работают нормально для приведения void * к другому типу указателя Есть ли веская причина отдать предпочтение одному другому?

Ответы [ 4 ]

121 голосов
/ 22 ноября 2008

Использование static_cast: это самый узкий состав, который точно описывает, какое преобразование сделано здесь.

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

Однако, это на самом деле не описывает эффект reinterpret_cast. Скорее, reinterpret_cast имеет несколько значений, для которых все считают, что «отображение, выполняемое reinterpret_cast, определяется реализацией». [5.2.10.3]

Но в частном случае приведения от void* к T* отображение полностью определено стандартом; а именно, чтобы назначить тип указателю без типа без изменения его адреса.

Это причина для предпочтения static_cast.

Кроме того, и, возможно, более важным является тот факт, что каждое использование reinterpret_cast совершенно опасно, потому что оно действительно преобразовывает что-либо во что-то еще (для указателей), тогда как static_cast гораздо более ограничительно, обеспечивая тем самым лучший уровень. защиты. Это уже спасло меня от ошибок, когда я случайно попытался привести один тип указателя к другому.

7 голосов
/ 22 ноября 2008

Это сложный вопрос. С одной стороны, Конрад делает отличное замечание относительно определения спецификации для reinterpret_cast , хотя на практике это, вероятно, делает то же самое. С другой стороны, если вы преобразуете между типами указателей (как это обычно бывает при индексировании в памяти через char *, например), static_cast сгенерирует ошибку компилятора, и вы будете вынуждены все равно используйте reinterpret_cast .

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

1 голос
/ 14 декабря 2009

Я предлагаю всегда использовать самые слабые заклинания.

reinterpret_cast может использоваться для наведения указателя на float. Чем более разрушительным является состав актеров, тем больше внимания требует его использование.

В случае char* я бы использовал приведение в стиле c, пока у нас не будет немного reinterpret_pointer_cast, потому что оно слабее и ничего другого недостаточно.

0 голосов
/ 22 ноября 2008

Мои личные предпочтения основаны на такой грамотности кода:

void* data = something;
MyClass* foo = reinterpret_cast<MyClass*>(data);
foo->bar();

или

typedef void* hMyClass; //typedef as a handle or reference
hMyClass = something;
const MyClass& foo = static_cast<MyClass&>(*hMyClass);
foo.bar();

Они оба делают то же самое в конце, но static_cast кажется более подходящим в среде промежуточного программного обеспечения, в то время как приведение к переинтерпретации больше похоже на то, что вы видели бы в библиотеке низкого уровня IMHO.

...