(我编辑了这个问题以避免分心。在任何其他问题有意义之前,需要先解决一个核心问题。向任何现在看来答案似乎不那么相关的人道歉。)
让我们设置一个具体的例子:
struct Base {
int i;
};
没有虚方法,也没有继承,通常是一个非常愚蠢和简单的对象。因此它是普通旧数据 (POD)它回归到可预测的布局。尤其:
Base b;
&b == reinterpret_cast<B*>&(b.i);
这是根据维基百科(其本身声称引用了 C++03 标准):
指向 POD 结构对象的指针(使用重新解释强制转换进行适当转换)指向其初始成员,反之亦然,这意味着 POD 结构的开头没有填充。 [8]
现在让我们考虑继承:
struct Derived : public Base {
};
同样,没有虚拟方法,没有虚拟继承,也没有多重继承。因此这也是 POD。
问题:这个事实(Derived 是 C++11 中的 POD)是否允许我们这样说:
Derived d;
&d == reinterpret_cast<D*>&(d.i); // true on g++-4.6
If这是正确的,那么以下将是明确定义的:
Base *b = reinterpret_cast<Base*>(malloc(sizeof(Derived)));
free(b); // It will be freeing the same address, so this is OK
我不是问关于new
and delete
这里 - 更容易考虑malloc
and free
。我只是好奇在这样的简单情况下有关派生对象布局的规定,以及基类的初始非静态成员位于可预测的位置。
派生对象是否应该等同于:
struct Derived { // no inheritance
Base b; // it just contains it instead
};
事先没有填充?