class 层次结构的内存布局
memory layout of class hierarchy
我的目标是创建 class 层次结构的 classes 实例,它们共享一些公共数据。我创建(使用联合)足够的内存,以便可以在分配的内存中创建最大的实例。现在我想创建/交换 class 的实例并在内存中使用 "old" 数据。这是 valid/legal 操作吗?
原始代码使用一些 MTP 内容来创建联合,目标是使用此 class 层次结构作为状态机实现的核心。我这里只展示包含问题的基本代码。
我看到如果基础 class 不包含虚方法但派生方法包含虚方法,这是一个问题。这是因为 vtable-pointer 位于内存前面(gcc on x86/linux)。
简单问题:如果基 class 的实例之前已创建并且内存与该派生的实例 class?
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();
}
不,这行不通,因为标准说:
9.5/1 : in a union, at most one of the non-static data members can be active at any time that is, the value of at most one of the
non-static data members can be stored in a union at any time.
您尝试做的是未定义的行为:
new (&u) Derived1; // RISKY !!!
使用 new 放置会覆盖之前在 u 中的对象,而不会正确销毁它。然后创建 Derived1
无论如何都会创建自己的基础。如果您以某种方式设法将旧值保留在内存中,它仍然是未定义的行为:它可以工作或不工作,具体取决于编译器的对象布局和实现。
这是未定义的行为 - 它可能看起来有效,但不可移植,不应依赖。
一个工会只能有一个活跃成员;构造 Derived1
会使之前发生的事情无效。
我的目标是创建 class 层次结构的 classes 实例,它们共享一些公共数据。我创建(使用联合)足够的内存,以便可以在分配的内存中创建最大的实例。现在我想创建/交换 class 的实例并在内存中使用 "old" 数据。这是 valid/legal 操作吗?
原始代码使用一些 MTP 内容来创建联合,目标是使用此 class 层次结构作为状态机实现的核心。我这里只展示包含问题的基本代码。
我看到如果基础 class 不包含虚方法但派生方法包含虚方法,这是一个问题。这是因为 vtable-pointer 位于内存前面(gcc on x86/linux)。
简单问题:如果基 class 的实例之前已创建并且内存与该派生的实例 class?
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();
}
不,这行不通,因为标准说:
9.5/1 : in a union, at most one of the non-static data members can be active at any time that is, the value of at most one of the non-static data members can be stored in a union at any time.
您尝试做的是未定义的行为:
new (&u) Derived1; // RISKY !!!
使用 new 放置会覆盖之前在 u 中的对象,而不会正确销毁它。然后创建 Derived1
无论如何都会创建自己的基础。如果您以某种方式设法将旧值保留在内存中,它仍然是未定义的行为:它可以工作或不工作,具体取决于编译器的对象布局和实现。
这是未定义的行为 - 它可能看起来有效,但不可移植,不应依赖。
一个工会只能有一个活跃成员;构造 Derived1
会使之前发生的事情无效。