【发布时间】:2015-01-31 18:14:10
【问题描述】:
我想知道我对reinterpret_cast 的以下使用是否是未定义的行为。
给定一个模板聚合,例如...
template<typename T>
struct Container
{
Container(T* p) : ptr(p) { }
...
T* ptr;
};
... 以及类似 ...
的类型层次结构struct A { };
struct B : A { };
鉴于B 是A 的动态类型,以下转换是否安全...
Container<B>* b = new Container<B>( new B() );
Container<A>* a = reinterpret_cast<Container<A>*>(b);
...就我现在可以安全地使用a->ptr 及其(可能是虚拟的)成员而言?
我使用它的代码编译和执行都很好(Clang,OS X),但我担心我已经放置了一个定时炸弹。我猜Container<T> 的每个实例都共享相同的布局和大小,所以这应该不是问题,对吧?
看看 cppreference.com 关于reinterpret_cast 的说法,似乎有一个合法用途的声明涵盖了我正在尝试做的事情......
类型别名 当指向 T1 类型对象的指针或引用被 reinterpret_cast(或 C 风格强制转换)到指向不同类型 T2 对象的指针或引用时,强制转换总是成功,但结果指针或引用只能在两个 T1和 T2 是标准布局类型,并且以下情况之一为真:
...
T2 是聚合类型或联合类型,它将上述类型之一作为元素或非静态成员(递归地包括子聚合的元素和所包含联合的非静态数据成员):这使得它可以安全地从结构的第一个成员和联合的元素转换到包含它的结构/联合。
我很感激我在这件事上似乎走错了路。这不是我关心的。我只想知道我所做的是否安全/合法。提前感谢您的帮助。
【问题讨论】:
-
Derive Container from Container 并且会自动工作。但是,这仍然没有保存,因为您可以将 C(这是从 A 派生的另一种类型)插入到 Container 中,然后在 Container 中得到一个 C,这可能不是你想要的。
-
如果我只处理类型
A和B那就太好了,但我想将它抽象为任何类型T以及T的派生类。 -
问题仍然存在:如果您将
Container<Derived>转换为对Container<Base>的可变引用,您将失去容器中元素属于Derived类型的保证。无论您如何实现此转换,都会存在此问题,即如果您蛮力 (reinterpret_cast) 或使用建议的方法从彼此派生容器,它是相同的。