Согласно стандарту C++, a reinterpret_cast
из указателя T*
к некоторому другому указателю типа Q*
может изменить или не изменить значение указателя в зависимости от реализации.
Мне очень интересно - это там любой реальный пример реализации C++ где, бросая указатель на некоторый другой тип указателя с reinterpret_cast
изменяет указатель? Какой и почему изменяется там?
Обратите внимание: когда в стандарте говорится, что он может или не может что-то делать, это не означает, что есть какая-либо текущая реализация, которая имеет такое поведение, только то, что они могут.
Самое близкое, что я могу придумать, - это архитектура, в которой выравнивание типов требовалось аппаратным обеспечением, и реализация, которая решила скорректировать выравнивание, если это необходимо. Что-то вроде:
aligned8 var;
aligned1 *p = reinterpret_cast<aligned1*>(&var);
aligned1 *q = p + 1; // assuming aligned 1 size is not multiple of 8
aligned8 *a = reinterpret_cast<aligned8*>(q); // [1]
Может быть требование, чтобы a
был действительным указателем, он должен адресовать позицию памяти, кратную 8, в то время как аргумент q
с меньшими требованиями к выравниванию может указывать на любой адрес памяти.
class A1 { int a1; };
class A2 { int a2; };
class B: public A1, public A2 { };
#define DBG(val) cout << #val << ": " << val << endl
// test code
B b;
DBG(&b); // prints 0x42
void *p_blank = &b;
DBG(p_blank); // prints 0x42
A2 *p_a2 = &b;
DBG(p_a2); // prints 0x46
void *p_reinterpreted = reinterpret_cast<A2*>(&b);
DBG(p_reinterpreted); // prints 0x42
A2 *p_reinterpreted2 = reinterpret_cast<A2*>(&b);
DBG(p_reinterpreted2); // prints 0x42
A2 *p_a2 = &b
означает дать мне указатель на объект A2 внутри объекта B.
reinterpret_cast
означает дать мне указатель на b и рассматривать его как указатель на A2.
Результат этого reinterpret_cast имеет тип 'указатель на A2', поэтому он не выдает предупреждения при присвоении переменной void* (или переменной A2*).