对象在内存中的样子是什么?

Nei*_*day 41 c++

可能重复:
内存中C++对象的结构与Struct
内存布局c ++对象有关

这可能是一个非常愚蠢的问题,但无论如何我会问.我很好奇对象在内存中的样子.显然,它必须包含其中的所有成员数据.我假设对象的函数不会在内存中重复(或者我错了?).在内存中拥有999个对象并且反复定义相同的功能似乎很浪费.如果内存中只有1个函数用于所有999个对象,那么每个函数如何知道要修改的成员数据(我特别想知道低级别).是否有一个对象指针被发送到幕后的函数?也许每个编译器都有所不同?

另外,static关键字如何影响这个?使用静态成员数据,我认为所有999个对象都将使用完全相同的内存位置作为其静态成员数据.这存储在哪里?静态函数我想它也只是内存中的一个位置,并且不必与实例化对象进行交互,我认为我理解.

ten*_*our 21

静态类成员的处理方式几乎与全局变量/函数一样.因为它们没有绑定到实例,所以没有什么可以讨论内存布局.

您可以想象,每个实例都会复制类成员变量,因为每个实例都可以为每个成员变量拥有自己的唯一值.

类成员函数仅在内存中的代码段中存在一次.在较低的层次上,它们就像普通的全局函数一样,但它们会收到一个指针this.使用x86上的Visual Studio,它通过ecx寄存器使用thiscall调用约定.

在谈论虚函数,多态时,内存布局变得更加复杂,引入了一个" vtable ",它基本上是一组定义类实例地形的函数指针.

  • 要迂腐,成员函数不会"收到指向`this`"的指针.相反,它是相反的.成员函数有一个隐式实例参数,在函数体中,`this`是指向该实例的指针. (2认同)
  • 即使有这样的描述,说该函数接收“this”指针仍然是正确的。它是通过“ecx”而不是堆栈传递的参数。或者也许是我没理解你的意思。 (2认同)

pad*_*ddy 6

你在这里问了几个问题......

布局

所有非静态成员都在内存中组织,就像结构一样.如果编译器选择放入任何内容,可能会有填充.如果你有一个对象数组,它就像一个结构数组

静态成员

显然是分开存放的.一份.

函数调用

课程幕后有一点魔力.当你调用一个成员函数时,它就像任何其他函数一样,除了它有不同的调用约定.实际上,这会将对象的指针(this)插入参数列表中.

[ 编辑:函数本身的代码不与您的对象一起存储 - 这允许您做有趣的事情,delete this并继续执行成员函数,前提是您不再访问刚删除的对象].

当你有重载或多态函数时,事情会变得更加神奇. 这篇文章解释说我在大约5秒内搜索了一下.我相信还有更多.我从不关心对象调用的内部,但知道它总是很好.

你应该尝试制作一个展示所有这些不同方面的课程,并观察每个案例中产生的装配.在调整一些时间关键代码之前,我已经做过了.


Zde*_*vic 5

您怀疑,数据成员(字段)是按顺序排列的。这也包括基类的字段。

如果该类(或其基类之一)包含任何虚拟方法,则布局通常以vptr开头,即指向虚拟表(或vtable)的指针,该虚拟表是与该类相关的函数实现的指针表。请注意,这不是标准定义的,但是AFAIK当前所有的编译器都使用这种方法。此外,通过多重继承,它变得更加毛茸茸,因此暂时不考虑它。

+-----------+
|  vptr     |  pointer to vtable which is located elsewhere
+-----------+
|  fieldA   |  first member
|  fieldB   |  ...
|  fieldC   |
|  ...      |
+-----------+
Run Code Online (Sandbox Code Playgroud)

字段可能会占用更多空间,而不是它们各自大小的总和,这取决于打包(例如1字节的打包可确保没有间隙,但就性能而言,其效率低于4或8字节的打包)。

成员函数(非静态)通常通过x86体系结构上的ecx寄存器接收指向对象的指针。该标准也未定义。

静态函数与全局函数相似,并且它们在数据段中的静态类字段(对于类的所有实例共享)上运行。