以下类包含一些相同类型的成员:
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
//...
};
又可能给出一个规律的模式。
答案 0 :(得分:3)
没有。没有规则要求它,因此编译器可以在任何地方插入填充。 “对齐要求可能......”仅仅是一个例子,而不是对可能原因的限制。
如果你有T m[5]
成员,那将是另一回事,在这种情况下&(this->m[1]) - &(this->m[0]) == 1
。
出于同样的原因,“编译器是否真的允许在任意数据成员之间插入与MyClass相关的信息(如vtable-ptr)?”必须得到积极的回答,因为没有任何规则禁止它。它无法将其插入子对象的中间(无论是T
还是T[5]
),但在子对象之间是可以的。