相关问题:标准布局和尾部填充
代码段:
#include <iostream>
#include <type_traits>
struct A0
{
int a;
char c;
};
struct B0 : A0
{ char d; };
struct A1
{
int a;
private:
char c;
};
struct B1 : A1
{ char d; };
struct A2
{
private:
int a;
char c;
};
struct B2 : A2
{ char d; };
int main()
{
std::cout << std::is_pod<A0>::value << ' ' << sizeof(B0) << std::endl; // 1 12
std::cout << std::is_pod<A1>::value << ' ' << sizeof(B1) << std::endl; // 0 8
std::cout << std::is_pod<A2>::value << ' ' << sizeof(B2) << std::endl; // 1 8
}
现场演示//使用g++
通常说,当您从带有尾部填充的POD类型继承时,由于某些历史原因,如果基类子对象是POD,则安腾ABI(老实说,我不知道这是什么(不允许重新使用基类子对象的尾部填充。
然而,在第三种情况下,A2
是POD,因为它的所有成员都具有相同的访问控制,但B2
正在重用这种尾部填充。为什么?
当前标准始终允许在任何基类子对象中重用对齐尾孔。它不一定是一个"POD"(或现代的等价物,"微不足道的可复制性"(。事实上,任何基类子对象都是"潜在重叠子对象",而"潜在重叠的子对象"是不可memcpy
的。
安腾ABI不跟踪当前标准中的POD或等效产品。根据C++98的定义,它允许(事实上强制(在任何不是POD的基本子对象中重用对齐尾孔。
1.1定义:
此ABI仅使用POD的定义来决定是否在基类子对象的尾部填充中分配对象。虽然这些标准随着时间的推移扩大了POD的定义,但它们也禁止程序员使用memcpy直接读取或写入基类子对象的底层字节。因此,即使在最保守的解释中,实现也可以在C++98中不属于POD的任何类的尾部填充中自由分配对象。此ABI符合此要求。
在C++98中,A2
不会是POD,因为它有私有成员。因此,GCC根据ABI重新使用尾部填充,并符合当前标准或任何以前的标准,可以追溯到C++98。