类和类的方法存储在哪里?
Where is the class and class's method stored?
内存可以划分为4个区域。
第一个是堆栈,第二个是堆,第三个是代码,最后一个是数据。
我想知道类和类的方法存储在哪里。
你能解释一下吗?
注意:理论上,这个答案的部分可能会有很大的差异(尽管事实上,至少在大多数典型/常见的实现中都有相当程度的一致性)。因此,这个答案的部分主要基于你通常可以预期的,尽管可能会有更多的变化。
"方法"(成员函数)是代码,与其他代码一起定位。与其他函数的主要区别在于,成员函数通常希望接收一个隐藏参数(称为this
),该参数为其提供任何对象数据的地址(间接包括类的vtable指针)。
类数据的位置通常取决于类对象的分配方式,就像任何其他变量一样:全局或静态本地对象将被静态分配(在列表之外,显然是"数据");一个局部自动变量将被自动分配(又名"在堆栈上"),一个动态分配的变量将被动态分配(大惊喜)(又名"堆上")。
当然,可以稍微改变这些规则——例如,static
成员变量将被静态分配,而不管对象的其余部分是如何分配的。
方法不占用实例存储。OOP创造了一种错觉——某个方法是类成员对象,但这只是一种范式,在现实中,你可以将成员方法视为全局函数,只在它们"关联"的对象范围内可见。
简而言之,C++成员方法SomeType.someMethod()
与C SomeType
结构和附带的SomeType_someMethod(SomeType* self)
是相同的,这是C++编译器自动生成的。
类中唯一实际占用实例数据空间的部分是非静态成员类型。因此,成员方法在逻辑上占据了内存的"代码"answers"数据"部分,因为方法正是这样——内存中全局和局部对象的指令和引用列表。
由于C++允许递归和所有其他"动态特性",函数的每个实例都实例化了自己的本地对象,因此非静态和非常量本地自动成员以立即值或全局静态数据引用的形式从全局内存复制到堆栈中。这只适用于非常量的局部成员数据,a方法不会更改其指令,所以与局部不同,只需要方法代码的一个实例。
因此,总而言之,成员方法,就像静态成员对象一样,不会占用实例空间,但是,当调用它们时,它们可能会占用堆栈空间,甚至可能导致递归情况下的堆栈溢出。
编辑:同样值得注意的是,在虚拟方法的情况下,它将占用每个对象的一个空指针空间来容纳虚拟表。此外,大多数多继承实现通常会使用多个vtable。
类的定义存储在程序的代码部分(如果你仔细想想,这是有意义的,因为定义实际上是一组函数,在概念上将对象作为名为"this"的附加参数)。然而,虚拟类的每个实例都需要包含一个指向其虚拟表的指针(以便能够执行动态调度),并且该指针将驻留在该实例碰巧被分配的任何位置(对于虚拟情况,通常位于堆上)。
那些坚持语言律师的人会指出,C++标准并没有规定堆和堆栈之类的东西。我很清楚这一点,但出于所有实际目的,这就是它的工作方式。
- 谷歌测试中的期望值存储在哪里
- 常量参数存储在哪里 (C++)?
- 此递归函数的每次迭代的值存储在哪里?
- 如何告诉本机节点模块所需的dll存储在哪里?
- 在哪里存储跨平台C++应用存储?
- 模板参数在 C++ 中存储在哪里?
- 存储在 C++ 编译器中的标识符的定义(不是声明)在哪里?
- 变量或标识符存储在C++中究竟在哪里?
- C++ - thread_local变量存储在哪里?
- 返回值存储在哪里?
- Cmake忽略了我所有关于在boost::beast存储库中在哪里找到提升的指令
- glVertexAttribDivisor 存储在哪里 - VAO、VBO 或全局状态?
- 虚拟函数在哪里使用 vpointer to vtable 来解析方法调用,非虚拟方法存储在哪里以及如何解析它们?
- 为什么类型转换对象不会更改其地址?有关对象类型的信息存储在哪里?
- 如果不在内存中,则在哪里存储表达式和常数
- C 在哪里存储固定大小数组的大小
- 在哪里存储Visitor模式中访问的每个元素的计算结果
- winsock在哪里存储套接字的ip地址?
- 在哪里存储用于OSX部署的Qt导入
- PST 文件中的日历邮件在哪里存储约会时间和日期