C++ + gcc:尾部填充重用和 PODs

C++ + gcc: tail padding reuse and PODs

相关问题:

片段:

#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
}

Live demo // 使用 g++

通常说,当您从具有尾部填充的 POD 类型继承时,出于某些历史原因,Itanium ABI(老实说,我不知道那是什么)不允许重新使用尾部填充基础-class 子对象的,如果这样的子对象是 POD。

然而,在第三种情况下,A2 是 POD,因为它的所有成员都具有相同的访问控制,但 B2 正在重用这种尾部填充。这是为什么?

当前标准始终允许在任何基础 class 子对象中重复使用对齐尾孔。它不一定是 "POD"(或现代的等价物,"trivially copyable")。实际上,任何基础 class 子对象都是 "potentially-overlapping subobject",并且 "potentially-overlapping subobjects" 不是 memcpy-able。

Itanium ABI 不跟踪什么是或不是 POD 或当前标准中的等效项。根据 C++98 的定义,它允许(事实上强制要求)对齐尾孔在任何不是 POD 的基础子对象中重复使用。

1.1 Definitions:

This ABI uses the definition of POD only to decide whether to allocate objects in the tail-padding of a base-class subobject. While the standards have broadened the definition of POD over time, they have also forbidden the programmer from directly reading or writing the underlying bytes of a base-class subobject with, say, memcpy. Therefore, even in the most conservative interpretation, implementations may freely allocate objects in the tail padding of any class which would not have been POD in C++98. This ABI is in compliance with that.

在 C++98 中,A2 不会是 POD,因为它有私有成员。因此 GCC 根据 ABI 重用尾部填充,并符合当前标准或任何以前的标准回到 C++98。