对象如何存储在C++;? < C++中的对象如何存储在内存中?< /p>

对象如何存储在C++;? < C++中的对象如何存储在内存中?< /p>,c++,memory,memory-management,C++,Memory,Memory Management,对于常规类,例如 class Object { public: int i1; int i2; char i3; int i4; private: }; 使用对象指针作为数组可以访问i1,如下所示 ((Object*)&myObject)[0] === i1? 关于SO的其他问题似乎表明,将结构强制转换为指针将指向POD类型的第一个成员。对于具有构造函数的类来说,如果有的话,这有什么不同? 另外,对于非POD类型,它在哪些方面有所不同

对于常规类,例如

class Object
    {
public:
    int i1;
    int i2;
    char i3;
    int i4;
private:
    };
使用对象指针作为数组可以访问i1,如下所示

((Object*)&myObject)[0] === i1?
关于SO的其他问题似乎表明,将结构强制转换为指针将指向POD类型的第一个成员。对于具有构造函数的类来说,如果有的话,这有什么不同? 另外,对于非POD类型,它在哪些方面有所不同

编辑:

因此,在内存中,上述类是否会按如下方式排列

[i1 - 4bytes][i2 - 4bytes][i3 - 1byte][padding - 3bytes][i4 - 4bytes]

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

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


底线是:如果可以避免的话,根本不要以这种方式访问类(也不要memset或memcpy它们)。如果必须这样做(为什么?),那么请注意准确地知道类对象在内存中的位置,并小心避免继承。

不同之处在于此技巧仅对POD类型有效。这就是一切。标准规定此强制转换对POD类型有效,但不保证非POD类型会发生什么。

通常重要的不是类是否具有构造函数:重要的是类是否具有任何虚拟方法。有关详细信息,请在谷歌搜索“vtable”和“vptr”。

。您强制转换到对象*,但忽略了获取地址。让我们重新提问如下:

((int*)&myObject)[0] == i1
你必须非常小心这样的假设。正如您定义的结构一样,这在您可能遇到的任何编译器中都应该是正确的。但是,正如其他人所说,对象的各种其他属性(您可能在示例中忽略了这些属性)将使其成为非POD,并且可能(可能以依赖于编译器的方式)使上述语句不正确

请注意,如果您询问过i3,我不会很快告诉您它会起作用——在这种情况下,即使对于普通的POD,对齐或端点也很容易让您出错

无论如何,如果可能的话,你应该避免这种事情。即使它现在运行良好,如果您(或任何其他不了解您正在使用此技巧的人)更改结构顺序或添加新字段,此技巧将在您使用过的所有位置失败,这可能很难找到


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

这实际上取决于编译器,或者更确切地说,由编译器决定内存布局

例如,可以混合使用公共、私有和受保护的成员变量,这样每个访问类型都是连续的。或者,派生类的成员变量可以与超类中未使用的空间交错

虚拟继承会让情况变得更糟,虚拟继承的基类可以在为特定实例分配的内存中的任何位置进行布局


POD不同,因为它需要与C兼容。

谢谢。将&添加到问题中。除了没有虚拟成员和继承之外,POD类还必须没有非公共数据成员,并且没有用户定义的构造函数或析构函数。它们还必须没有非POD数据成员。类和结构之间的区别无关紧要:重要的是POD还是非POD。。。。在实践中,有各种各样的非POD类,大多数编译器都会将它们作为POD进行布局。依赖这种方法是不明智的,除非是因为特定编译器的文档中做出了保证。你确定POD类不能使用继承吗?如果它们只从一个POD类型继承呢?你可能在填充方面是对的,只要int是4字节宽,char是1字节宽。