相同类型的类成员之间的填充是否始终相同?

时间:2010-06-29 11:16:02

标签: c++ class struct padding

以下类包含一些相同类型的成员:

template <typename T>
class MyClass
{
    T m0;
    T m1;
    T m2;
    T m3;
    T m4;
    //...
};

成员都是在没有介入访问说明符的情况下声明的,因此被分配为后来的成员具有更高的地址(ISO / IEC 14882:9.2.12)。同一段落说:

  

实施对齐要求   可能导致两个相邻的成员没有   每次之后立即分配   其他;所以可能需要空间来管理虚函数(10.3)和虚基类(10.1)。

现在让我们假设MyClass没有虚函数,也没有虚基类。以下总是如此吗?

//inside a member function of MyClass

(char*)&m0 == (char*)&m0 + ((char*)&m1-(char*)&m0) * 0
(char*)&m1 == (char*)&m0 + ((char*)&m1-(char*)&m0) * 1
(char*)&m2 == (char*)&m0 + ((char*)&m1-(char*)&m0) * 2
(char*)&m3 == (char*)&m0 + ((char*)&m1-(char*)&m0) * 3
(char*)&m4 == (char*)&m0 + ((char*)&m1-(char*)&m0) * 4

或者编译器是否允许使用比所需更多的填充(无论出于何种原因......)?例如:如果sizeof(T)== 4和alignof(T)== 8,编译器将在成员之间使用4个填充字节。仅在m2和m3之间使用12个填充字节是否有效?

当MyClass具有虚拟功能或虚拟基类时,情况如何?是否真的允许编译器在任意数据成员之间插入与MyClass相关的信息(如vtable-ptr)?或者上面标准中的句子是否与T的虚函数和虚基类有关?因为如果存储与T外T相关的信息是有效的,它也可以具有以下含义:

template <typename T>
class MyClass
{
    T m0;
    //space to manage virtual functions and base classes of m0
    //padding
    T m1;
    //space to manage virtual functions and base classes of m1
    //padding
    T m2;
    //space to manage virtual functions and base classes of m2
    //...
};

又可能给出一个规律的模式。

1 个答案:

答案 0 :(得分:3)

没有。没有规则要求它,因此编译器可以在任何地方插入填充。 “对齐要求可能......”仅仅是一个例子,而不是对可能原因的限制。

如果你有T m[5]成员,那将是另一回事,在这种情况下&(this->m[1]) - &(this->m[0]) == 1

出于同样的原因,“编译器是否真的允许在任意数据成员之间插入与MyClass相关的信息(如vtable-ptr)?”必须得到积极的回答,因为没有任何规则禁止它。它无法将其插入子对象的中间(无论是T还是T[5]),但在子对象之间是可以的。