类和类的方法存储在哪里?

Where is the class and class's method stored?

本文关键字:在哪里 存储 方法      更新时间:2023-10-16

内存可以划分为4个区域。

第一个是堆栈,第二个是堆,第三个是代码,最后一个是数据。

我想知道类和类的方法存储在哪里。

你能解释一下吗?

注意:理论上,这个答案的部分可能会有很大的差异(尽管事实上,至少在大多数典型/常见的实现中都有相当程度的一致性)。因此,这个答案的部分主要基于你通常可以预期的,尽管可能会有更多的变化。

"方法"(成员函数)是代码,与其他代码一起定位。与其他函数的主要区别在于,成员函数通常希望接收一个隐藏参数(称为this),该参数为其提供任何对象数据的地址(间接包括类的vtable指针)。

类数据的位置通常取决于类对象的分配方式,就像任何其他变量一样:全局或静态本地对象将被静态分配(在列表之外,显然是"数据");一个局部自动变量将被自动分配(又名"在堆栈上"),一个动态分配的变量将被动态分配(大惊喜)(又名"堆上")。

当然,可以稍微改变这些规则——例如,static成员变量将被静态分配,而不管对象的其余部分是如何分配的。

方法不占用实例存储。OOP创造了一种错觉——某个方法是类成员对象,但这只是一种范式,在现实中,你可以将成员方法视为全局函数,只在它们"关联"的对象范围内可见。

简而言之,C++成员方法SomeType.someMethod()与C SomeType结构和附带的SomeType_someMethod(SomeType* self)是相同的,这是C++编译器自动生成的。

类中唯一实际占用实例数据空间的部分是非静态成员类型。因此,成员方法在逻辑上占据了内存的"代码"answers"数据"部分,因为方法正是这样——内存中全局和局部对象的指令和引用列表。

由于C++允许递归和所有其他"动态特性",函数的每个实例都实例化了自己的本地对象,因此非静态和非常量本地自动成员以立即值或全局静态数据引用的形式从全局内存复制到堆栈中。这只适用于非常量的局部成员数据,a方法不会更改其指令,所以与局部不同,只需要方法代码的一个实例。

因此,总而言之,成员方法,就像静态成员对象一样,不会占用实例空间,但是,当调用它们时,它们可能会占用堆栈空间,甚至可能导致递归情况下的堆栈溢出。

编辑:同样值得注意的是,在虚拟方法的情况下,它将占用每个对象的一个空指针空间来容纳虚拟表。此外,大多数多继承实现通常会使用多个vtable。

类的定义存储在程序的代码部分(如果你仔细想想,这是有意义的,因为定义实际上是一组函数,在概念上将对象作为名为"this"的附加参数)。然而,虚拟类的每个实例都需要包含一个指向其虚拟表的指针(以便能够执行动态调度),并且该指针将驻留在该实例碰巧被分配的任何位置(对于虚拟情况,通常位于堆上)。

那些坚持语言律师的人会指出,C++标准并没有规定堆和堆栈之类的东西。我很清楚这一点,但出于所有实际目的,这就是它的工作方式。