类与结构的内存布局如何?

iQt*_*iQt 11 c c++ struct class language-lawyer

我来自C编程,其中结构中的数据首先是顶部变量,然后是第二个,第三个,依此类推.

我现在用C++编程,而我正在使用类.我基本上想要实现相同的目标,但我也想要获取/设置方法,也可能需要其他方法(我也想尝试用C++风格进行操作,并且可能会学到新东西).

是否有保证,例如公共变量将首先在内存中,然后是私有变量?

Col*_*mbo 17

是否有保证,例如公共变量将首先在内存中,然后是私有变量?

没有,这样的保证是作出- C++ 11标准,[class.mem]/14:

分配具有相同访问控制(第11条)的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址.未指定具有不同访问控制的非静态数据成员的分配顺序(11).

所以

struct A
{
    int i, j;
    std::string str;

private:

    float f;

protected:

    double d;
};
Run Code Online (Sandbox Code Playgroud)

只保证对于给定的类型对象A,

  • i的地址小于j
  • j 地址小于 str

请注意,类键structclass布局没有任何区别:它们唯一的区别是只在编译时存在的访问权限.


它只说顺序,但不是第一个变量实际上从"第一个地址"开始?让我们假设一个没有继承的类.

是的,但仅适用于标准布局类.类必须满足一系列要求才能成为标准布局类,其中之一是所有成员都具有相同的访问控制.
引用C++ 14(同样适用于C++ 11,但措辞更为间接),[class.mem]/19:

如果标准布局类对象具有任何非静态数据成员,则其地址与其第一个非静态数据成员的地址相同.否则,其地址与其第一个基类子对象的地址(如果有)相同.[ 注意:因此,在标准布局结构对象中可能存在未命名的填充,但不是在其开头,以实现适当的对齐.- 结束说明 ]

[类]/7:

一个标准布局类是一类:

  • 没有非标准布局类(或此类类型的数组)或引用类型的非静态数据成员,
  • 没有虚函数(10.3),也没有虚基类(10.1),
  • 对所有非静态数据成员具有相同的访问控制(第11条),
  • 没有非标准布局基类,
  • 或者在最派生类中没有非静态数据成员,并且最多只有一个具有非静态数据成员的基类,或者没有具有非静态数据成员的基类,并且
  • 没有与第一个非静态数据成员相同类型的基类.110

110)这确保具有相同类类型并且属于相同的最大派生对象的两个子对象不被分配在同一地址(5.10).


das*_*ght 5

第一件事,第一:classstructC++中都大同小异-唯一的区别是,在第一次访问说明符之前的所有成员class都属于个人,而在struct他们是公开的.

是否有保证,例如公共变量将首先在内存中,然后是私有变量?

没有这样的保证.如果没有继承,则将按照在同一访问组中声明它们的顺序将内存分配给类成员.由编译器决定是否应将公共成员变量置于私有/受保护变量之前,反之亦然.与C一样,C++可以在类成员之间添加填充.

继承使事情变得更复杂,因为基类的数据成员也需要放在派生类中.最重要的是,存在虚拟继承和多重继承,具有复杂的规则.

我基本上想要实现相同的[布局],但我也想要get/set方法,也可能是其他方法.

如果您将类的所有数据成员设为私有,并添加访问器成员函数(这就是C++从其他语言中调用"方法"),您将实现此效果.