类层次结构的内存布局

时间:2015-04-25 12:25:59

标签: c++ unions memory-layout

我的目标是创建一个类层次结构的类的实例,它们共享一些公共数据。我创建(使用union)足够的内存,以便可以在分配的内存中创建最大的实例。现在我想创建/交换类的实例并使用" old"数据存储在那里。这是有效/合法的操作吗?

原始代码使用一些MTP内容来创建联合,目标是使用此类层次结构作为状态机实现的核心。我只在这里显示包含问题的基本代码。

我看到如果基类不包含虚拟方法但导出的方法不存在,则会出现问题。这是因为vtable-pointer位于内存前面(在x86 / linux上使用gcc)。

简单问题:如果先前创建了基类的实例并且内存与该派生类的实例一起重用,派生类的实例是否可以从基类访问数据?

class Base
{
    public:
        int a;
        Base()=default;
        Base( int _a):a(_a){}

        void Print() { cout << "Value: " << a << endl; }
};

class Derived1: public Base
{
    public:
        int d;

        Derived1(): d( 0x11223344){}
};

union  U
{   
    U(){}
    Base base;
    Derived1 derived1;
} u;

int main()
{
    memset( &u, 0, sizeof(u));

    new (&u) Base(12345678);
    u.base.Print();

    new (&u) Derived1;
    u.base.Print();
 }

2 个答案:

答案 0 :(得分:1)

没有这不会起作用,因为沙漠说:

  联盟中的

9.5 / 1:,最多只有一个非静态数据成员可以随时处于活动状态,即最多其中一个的值   非静态数据成员可以随时存储在联合中。

您尝试做的是未定义的行为:

new (&u) Derived1;  // RISKY !!!

使用新的展示位置,您可以覆盖之前的对象,而不会正确销毁它。然后Derived1的创建无论如何都会创建自己的基础。如果你以某种方式设法将旧值保留在内存中,它仍然是未定义的行为:它可以工作与否,具体取决于编译器的对象布局和实现。

答案 1 :(得分:0)

这是未定义的行为 - 它似乎可行,但不可移植,不应该依赖。

工会只能有一名活跃会员;构建Derived1会使以前的内容无效。