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

发布于 2024-11-18 08:45:33 字数 326 浏览 6 评论 0原文

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

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

While answering one of the question, there was a discussion thread below my answer. Which suggests that depending on the access specifier (or may be the type of inheritance) private/protected/public the sizeof the class object may vary!

I still don't understand from their brief discussion, how is that possible ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

舂唻埖巳落 2024-11-25 08:45:33

注意下面 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 重新排序到 b 之前,强制在 ab 之间以及 c 之后插入额外的填充填充到对象的末尾(使得 sizeof( 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;
};

,它将 abc 置于不同的访问控制中。

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

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

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


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

Note new language for C++11 below

In C++03, there is language that makes this possible, 9.2 [class.mem]/12 (emphasis mine):

Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).

So given this definition:

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

on a system with 32 bit (int) alignment, the compiler is not allowed to reorder c to come before b, forcing the insertion of additional padding padding in between a and b, and after c to the end of the object (making sizeof(Foo) == 12). However, for this:

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

a and (b and c) are separated by an access specifier, so the compiler is free to perform such reordering, making

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

sizeof(Foo) == 8.

In C++11, the language changes slightly. N3485 9.2 [class.mem]/13 says (emphasis mine):

Nonstatic data members of a (non-union) class with the same access control (Clause 11) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified (Clause 11). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).

This means that in C++11, in the above example (separated by 3 publics), the compiler is still not allowed to perform the reordering. It would have to be something like

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

, which places a, b, and c with different access control.

Note that under the C++11 rules, given a definition like:

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

the compiler must put d after b, even though they are separated by access specifiers.


(That said, I'm not aware of any implementation that actually takes advantage of the latitude offered by either standard)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文