布局上的POD类型的大小和对齐,由基本的C ABI指定,但有以下附带规定:

  • 如果基本ABI为C99类型_Bool指定了规则,则bool将遵循这些规则。否则,它的大小和对齐为1。
  • 如果基本ABI没有为空类指定规则,则空类的大小和对齐为1
  • 类型T &T &&与指针类型T*的大小与对齐完全相同
  • 成员指针类型被视为一个特定的C类型处理,详见

这些类型的_dsize_、_nvsize_和_nvalign_被定义为它们常规的大小和对齐。这几个属性只在非空类作为基类时才会用到,普通POD类型不需要单独考虑它们。对于POD类型,我们会忽略其尾部填充,因为:

  • ①在CWG(Core Working Group)问题43被解决之前,标准不允许我们将尾部填充用于其他用途;
  • ②忽略尾部填充有时能让该类型的拷贝操作更快。
Paw5zx个人理解:点击查看更多

这里的忽略,应该指的是早期C++标准禁止复用尾部填充来存放额外成员,所以ABI只能把它保留为占位符

Paw5zx个人理解:点击查看更多

根据C++ Standard Draft 的2025-07-25版本中的内容
POD类是:

  • 具有trivial和standard-layout属性的类,并且
  • 其所有非静态数据成员都不能是非POD类类型或非POD类类型的数组

平凡相关定义:

平凡类(trivial class):

  • 是一个平凡可复制类
  • 有一个或多个可用(eligible)的默认构造函数,并且所有这些默认构造函数都是平凡的

平凡可复制类(trivial copyable class):

  • 至少有一个可用的拷贝构造函数,移动构造函数,拷贝赋值运算符或移动赋值运算符,并且
  • 每个可用的拷贝构造函数,移动构造函数,拷贝赋值运算符和移动赋值运算符都是平凡的,并且
  • 有平凡的、非删除的析构函数

平凡默认构造函数:
类X的默认构造函数是平凡的,当且仅当同时满足以下条件:

  • 它不是用户提供的,并且
  • X没有虚函数以及虚基类,并且
  • X的所有非静态数据成员都没有默认初始值,并且
  • X的所有直接基类都具有平凡默认构造函数,并且
  • 要么X是个联合体,要么X所有非静态类类型成员(或类类型数组)的默认构造函数也是平凡的

平凡拷贝/移动构造函数:
类X的拷贝/移动构造函数是平凡的,当且仅当同时满足以下条件:

  • 它不是用户提供的,并且
  • X没有虚函数以及虚基类,并且
  • X的所有直接基类的拷贝/移动构造函数也是平凡的,并且
  • X所有非静态类类型成员(或类类型数组)的拷贝/移动构造函数也是平凡的

平凡析构函数;
类X的析构函数是平凡的,当且仅当同时满足以下条件:

  • 它不是用户提供的,并且
  • 非虚,并且
  • X的所有直接基类都有非平凡析构函数,并且
  • 要么X是个联合体,要么X所有非静态类类型成员(或类类型数组)的析构函数也是平凡的

standard-layout相关定义:
类S是标准布局类,当且仅当同时满足以下条件:

  • 没有非标准布局类类型的非静态数据成员(或者非标准布局类类型数组),没有引用类型的成员
  • 没有虚函数以及虚基类
  • 所有非静态数据成员的访问控制(public、protected、private)必须相同
  • 所有基类都是标准布局类
  • 每个基类类型(类型任意)至多有一个子对象
  • 所有非静态数据成员和位域必须在同一个类中首次声明,要么在都基类中,要么在都派生类中,不可分散
  • 基类不能是集合M(S)中的类型,对于类型X来说,M(X)定义如下:
    • 如果X是一个没有非静态数据成员的非联合体类类型,那么集合M(X)为空
    • 如果X是一个非联合体类类型,且具有类型为X₀的非静态数据成员,该成员要么是零大小的,要么是X的第一个非静态数据成员(该成员可以是匿名联合体),则集合M(X)由X₀和M(X₀)的元素组成。
    • 如果X是一个联合体类型,则集合M(X)是所有M(Uᵢ)的并集以及包含所有Uᵢ的集合的并集,其中每个Uᵢ是X的第i个非静态数据成员的类型。
    • 如果X是元素类型为Xₑ的数组类型,则集合M(X)由Xₑ和M(Xₑ)的元素组成。
    • 如果X是非类、非数组类型,则集合M(X)为空。

M(X)是所有可以在X的0偏移量处存在的所有非基类子对象的类型的集合,即如果某个类型T即做为S的基类出现,又属于M(S),那么S不是标准布局类。