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

时间:2014-11-14 22:04:46

标签: c++ c class struct language-lawyer

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

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

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

2 个答案:

答案 0 :(得分:17)

  

是否有保证,例如公共变量将成为第一个   内存然后私有变量?

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

  

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

所以

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

private:

    float f;

protected:

    double d;
};

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

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

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


  

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

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

  

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

[类] / 7:

  

标准布局类是一个类:

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

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

答案 1 :(得分:5)

第一件事:C ++中的classstruct非常相似 - 唯一的区别是class中第一个访问说明符之前的所有成员都被认为是私有的,而在struct他们是公开的。

  

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

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

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

  

我基本上想要实现相同的[布局],但我也想要get / set方法以及其他方法。

如果您将类的所有数据成员设为私有,并添加访问者成员函数(这是C ++调用的内容和#34;方法"来自其他语言),您将实现此效果。