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

2021-12-21 00:00:00 memory memory-management c++

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

对于常规类,例如

class 对象{上市:国际 i1;国际 i2;字符 i3;国际 i4;私人的:};

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

((Object*)&myObject)[0] === i1?

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

在内存中,上面的类会像下面这样排列吗?

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

解决方案

差不多.您强制转换为 Object*,而忽略了获取地址.让我们重新提问如下:

((int*)&myObject)[0] == i1

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

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

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

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

How are objects stored in memory in C++?

For a regular class such as

class Object
    {
public:
    int i1;
    int i2;
    char i3;
    int i4;
private:
    };

Using a pointer of Object as an array can be used to access i1 as follows?

((Object*)&myObject)[0] === i1?

Other questions on SO seem to suggest that casting a struct to a pointer will point to the first member for POD-types. How is this different for classes with constructors if at all? Also in what way is it different for non-POD types?

Edit:

In memory therefore would the above class be laid out like the following?

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

解决方案

Almost. You cast to an Object*, and neglected to take an address. Let's re-ask as the following:

((int*)&myObject)[0] == i1

You have to be really careful with assumptions like this. As you've defined the structure, this should be true in any compiler you're likely to come across. But all sorts of other properties of the object (which you may have omitted from your example) will, as others said, make it non-POD and could (possibly in a compiler-dependent way) make the above statement not true.

Note that I wouldn't be so quick to tell you it would work if you had asked about i3 -- in that case, even for plain POD, alignment or endianness could easily screw you up.

In any case, you should be avoiding this kind of thing, if possible. Even if it works fine now, if you (or anybody else who doesn't understand that you're doing this trick) ever changes the structure order or adds new fields, this trick will fail in all the places you've used it, which may be hard to find.

Answer to your edit: If that's your entire class definition, and you're using one of the mainstream compilers with default options, and running on an x86 processor, then yes, you've probably guessed the right memory layout. But choice of compiler, compiler options, and different CPU architecture could easily invalidate your assumptions.

相关文章