对象如何在C++中存储在内存中?

Dyn*_*ite 9 c++ memory memory-management pod

对象如何在C++中存储在内存中?

对于常规课程,如

class Object
    {
public:
    int i1;
    int i2;
    char i3;
    int i4;
private:
    };
Run Code Online (Sandbox Code Playgroud)

使用Object作为数组的指针可以用来访问i1如下?

((Object*)&myObject)[0] === i1?
Run Code Online (Sandbox Code Playgroud)

关于SO的其他问题似乎暗示将结构转换为指针将指向POD类型的第一个成员.如果有构造函数的类,这有什么不同?另外,对于非POD类型,它有何不同?

编辑:

因此,在记忆中,上述课程的布局如下:

[i1 - 4bytes][i2 - 4bytes][i3 - 1byte][padding - 3bytes][i4 - 4bytes]
Run Code Online (Sandbox Code Playgroud)

Lar*_*itz 16

几乎.你转换为一个Object*,而忽略了一个地址.让我们重新询问如下:

((int*)&myObject)[0] == i1
Run Code Online (Sandbox Code Playgroud)

你必须非常小心这样的假设.正如您已定义的结构一样,在您可能遇到的任何编译器中都应如此.但是,正如其他人所说,对象的各种其他属性(你可能已经从你的例子中省略)将使其成为非POD并且可能(可能以编译器相关的方式)使上述陈述不正确.

请注意,如果你问过i3,我就不会这么快告诉你它会起作用 - 在这种情况下,即使对于普通的POD,对齐或字节顺序也很容易搞砸你.

无论如何,如果可能的话,你应该避免这种事情.即使它现在工作正常,如果你(或任何不理解你正在做这个技巧的人)改变结构顺序或添加新字段,这个技巧将在你使用它的所有地方失败,这可能很难找到.

回答你的编辑:如果这是你的整个类定义,并且你正在使用一个带有默认选项的主流编译器,并在x86处理器上运行,那么是的,你可能已经猜到了正确的内存布局.但是,编译器,编译器选项和不同CPU架构的选择很容易使您的假设无效.


Soa*_*Box 5

没有虚拟成员和没有继承的类在内存中布局就像结构一样.但是,当你开始获得继承级别时,事情会变得棘手,很难弄清楚内存中的顺序(特别是多重继承).

当你有虚拟成员时,它们在内存中有一个"vtable",它包含指向实际函数的指针,该函数是根据类的继承层次结构创建的.

底线是:如果你能避免它,就不要以这种方式访问​​类(也不要记住它们或记忆它们).如果你必须这样做(为什么?),那么请注意你确切知道你的类对象将如何在内存中,并小心避免继承.