结构中的内存布局差异

时间:2018-03-21 13:12:45

标签: c++ memory struct

我在C ++中有以下结构

it("should clear canvas on each frame draw", async () => {
    await mount(<CoinsAndStars stars={true} coins={true} DeviceSupport={DeviceSupport} />);
    ctxMock.clearRect = jest.fn();
    jest.runOnlyPendingTimers();
    expect(ctxMock.clearRect).toHaveBeenCalledTimes(1);
    jest.runOnlyPendingTimers();
    expect(ctxMock.clearRect).toHaveBeenCalledTimes(2);
    jest.runOnlyPendingTimers();
    expect(ctxMock.clearRect).toHaveBeenCalledTimes(3);
});

此结构与添加了函数的结构之间的内存布局是否存在差异?

struct A {
  int a;
  double b;
  float c;
}

4 个答案:

答案 0 :(得分:8)

C ++标准保证C结构和C ++类(或结构 - 相同的东西)的内存布局是相同的,只要C ++类/结构符合POD标准(&#34; Plain Old)数据&#34)。 POD是什么意思?

如果出现以下情况,则类或结构为POD:

所有数据成员都是公共的,他们自己是POD或基本类型(但不是引用或指向成员类型的类型),或者是这样的数组

  • 它没有用户定义的构造函数,赋值运算符或析构函数
  • 它没有虚拟功能
  • 没有基类

在你的情况下,是的,内存布局是相同的。

来源:Structure of a C++ Object in Memory Vs a Struct

答案 1 :(得分:6)

  

此结构与添加了函数的结构之间的内存布局是否存在差异?

可能。

由于AB是标准布局 1 ,并且它们的公共初始序列由每个非静态数据成员 2 组成,因此它们布局兼容

标准仅描述抽象机器的语义,因此没有保证类型为A的对象将在内存中表示为B类型的对象,但布局兼容的类型往往是。

1) [class]/7

  

标准布局类是一个类:

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

2) [class.mem]/21&amp; [class.mem]/22

  

如果两个标准布局结构(第9类)类型具有相同数量的非静态数据成员,并且相应的非静态数据成员(按声明顺序)具有布局兼容类型(3.9),则它们是布局兼容的。 / p>

答案 2 :(得分:2)

它正式取决于您的编译器,但是声明非虚拟成员函数的编译器会改变类的布局,这将是边缘破坏。您需要这种稳定性来强制实现共享对象依赖于每个平台的兼容性。

答案 3 :(得分:1)

是,不......

在您的具体情况下,没有。结构只不过是一个数据容器,而且函数位于其他地方。调用该函数时,指向结构的指针将作为附加的隐式第一个参数传递,该参数在函数中显示为this指针。

但是,如果添加虚拟功能,则会发生变化。虽然C ++标准没有强制要求,但是vtable是 defacto 标准,并且该类将首先接收指向vtable的指针,但是不可见的成员。您可以通过在添加虚拟函数之前和之后打印出对象的大小来尝试此操作。

另一方面,如果类已经虚拟,因为从已经具有虚函数的另一个类继承,内存布局再也不会改变,因为已经存在指针包含的vtable(虽然它将指向子类实例的不同位置)。