Могу ли я привести пример из реальной жизни, где приведение через void * работает, а reinterpret_cast - нет? - PullRequest
8 голосов
/ 06 июля 2011

Существует ряд вопросов, касающихся перекрестных бросков (приведенных от T1* к несвязанным T2*), например , это и , это .Ответ обычно выглядит следующим образом: reinterpret_cast определяется реализацией, а преобразование в void*, за которым следует static_cast, четко определено.Тем не менее, я не вижу реальных примеров того, что может пойти не так, когда используется reinterpret_cast.

В каких реальных примерах используется приведение через void*, а reinterpret_cast - нет?

Ответы [ 2 ]

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

реальных примеров, когда приведение через void * работает, а reinterpret_cast не

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

reinterpret_cast<TYPE*&> (ссылка на указатель) может нарушить правило строгого псевдонима (по крайней мере, для g ++) и приведет вас к неопределенномуповедение. Demo .

Однако, static_cast<void*&> приведет к ошибке компилятора и избавит вас от такого неопределенного поведения. Демо .

Я видел такое использование в умном указателе:

template<class TYPE>
struct SmartPointer
{
  void *p;
  TYPE& operator ++ ()
  {
    (reinterpret_cast<TYPE*&>(p))++;  // breaking strict aliasing rule
    return *this;
  }
}
0 голосов
/ 06 июля 2011

приведение от T1 * к несвязанному T2 * с reinterpret_cast не менее определено, чем с static_cast.На самом деле, когда T1 и T2 являются стандартными типами макетов, они работают одинаково (см. 5.2.10 / 7):

Когда значение типа v указателя на T1 преобразуется в тип «указатель на cv T2 ”, результат static_cast(static_cast(v))

Для нестандартных типов макетов результат преобразования не определен, но он также не указан для static_cast.

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


struct Foo
{
};

struct Bar
{
    operator void*()
    {
        return 0;
    }
};

int main ()
{
  Bar b;
  Foo * p1 = static_cast<Foo*>(static_cast<void *>(b)); // ok, Bar::operator void* -> static_cast
  Foo * p2 = reinterpret_cast<Foo*>(b); // error, no conversion from Bar to Foo*.
}

...