对象的大小是否受访问说明符类型和继承类型的影响?

iam*_*ind 10 c++ inheritance access-specifier

在回答其中一个问题时,我的回答下面有一个讨论主题.这表明,根据访问符(或者可能是继承的类型)private/protected/publicsizeofclass对象可能会有所不同!

从他们的简短讨论中我仍然不明白,这怎么可能?

Bil*_*eal 16

请注意下面的C++ 11的新语言

在C++ 03中,有一种语言可以实现这一点,9.2 [class.mem]/12(强调我的):

声明没有插入访问说明符的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址.由访问说明符分隔的非静态数据成员的分配顺序未指定(11.1).实施对齐要求可能导致两个相邻成员不能立即分配; 因此,可能需要空间来管理虚拟功能(10.3)和虚拟基类(10.1).

所以给定这个定义:

class Foo
{
    char a; //8 bits
    // a must come before b, so 3 bytes of padding have to go here to satisfy alignment
    int b; //32 bits
    char c; //8 bits
    // 24 bits of padding required to make Foo a multiple of sizeof(int)
};
Run Code Online (Sandbox Code Playgroud)

具有32位(在系统上int)对准,编译器是不允许重新排序c来之前b,迫使附加填充填充的插入间ab,和后c向对象的尾部(使sizeof(Foo) == 12).但是,为此:

class Foo
{
    char a;
public:
    int b;
public:
    char c;
};
Run Code Online (Sandbox Code Playgroud)

a和(bc)由访问说明符分隔,因此编译器可以自由地执行这样的重新排序

memory-layout Foo
{
    char a; // 8 bits
    char c; // 8 bits
    // 16 bits of padding
    int b; // 32 bits
};
Run Code Online (Sandbox Code Playgroud)

sizeof(Foo) == 8.

在C++ 11中,语言略有变化.N3485 9.2 [class.mem]/13说(强调我的):

分配具有相同访问控制(第11条)的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址.具有不同访问控制的非静态数据成员的分配顺序未指定(第11条).实施对齐要求可能导致两个相邻成员不能立即分配; 因此,可能需要空间来管理虚拟功能(10.3)和虚拟基类(10.1).

这意味着在C++ 11中,在上面的示例中(由3个公共分隔),仍然不允许编译器执行重新排序.它必须是这样的

class Foo
{
    char a;
public:
    int b;
protected:
    char c;
};
Run Code Online (Sandbox Code Playgroud)

,放置a,b以及c不同的访问控制.

请注意,根据C++ 11规则,给定如下定义:

class Foo
{
    char a;
public:
    int b;
protected:
    char c;
public:
    int d;
};
Run Code Online (Sandbox Code Playgroud)

编译器必须放在d后面b,即使它们被访问说明符分开.


(也就是说,我不知道任何实际利用任何标准提供的宽容度的实现)