10

在回答其中一个问题时,我的回答下方有一个讨论线程。这表明根据访问说明符(或可能是继承类型),private/protected/public对象可能会有所不同!sizeofclass

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

4

1 回答 1

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)
};

在具有 32 位 ( int) 对齐的系统上,编译器不允许重新排序c到 before ,从而强制在 和 之间和之后b插入额外的填充填充到对象的末尾(制作)。但是,为此:abcsizeof(Foo) == 12

class Foo
{
    char a;
public:
    int b;
public:
    char c;
};

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

memory-layout Foo
{
    char a; // 8 bits
    char c; // 8 bits
    // 16 bits of padding
    int b; // 32 bits
};

sizeof(Foo) == 8.

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

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

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

class Foo
{
    char a;
public:
    int b;
protected:
    char c;
};

, 哪些地方a,bc具有不同的访问控制。

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

class Foo
{
    char a;
public:
    int b;
protected:
    char c;
public:
    int d;
};

编译器必须放在d之后b,即使它们由访问说明符分隔。


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

于 2011-07-05T04:42:25.113 回答