C++中函数的内存分配

7
我仍是C++的新手。刚了解到类的静态成员函数不是特定于对象的——所有对象都共享同一个成员函数副本。
现在,我有两个问题:
1. 在内存分配方面,普通函数和静态函数有什么区别?
2. 如果成员函数包含一些局部变量呢?在这种情况下,该函数“应该”具有一个单独的变量副本——特定于调用函数的对象...在C++中如何解决这个问题?
谢谢!

我想更正我的问题:在我的第二个问题中,我所指的“成员函数”是“静态成员函数”。 - dev
4个回答

9
仅从内存分配方面来说,普通函数和静态函数有什么区别?
没有区别。静态函数就像全局函数一样,只是作用域不同。
即使对于非静态成员函数,也不需要额外的内存。成员函数`int C::f(int arg1, int arg2)`只是一种语法糖,类似于`int C__f(C* this, int arg1, int arg2)`。
如果成员函数包含一些局部变量怎么办?在这种情况下,函数应该为调用该函数的对象“单独”拥有该变量的副本...
每次调用函数都会有局部变量的副本(除非它们是静态的)。这就是为什么C ++中可以进行递归。
那么如何解决这个问题?
函数调用基于“堆栈帧”。堆栈帧由以下内容组成:
- 函数参数(包括适用的隐式this)。 - 函数中任何其他非静态局部变量。 - “返回地址”,告诉处理器在函数完成后恢复执行的位置。
每次调用函数时,都会创建一个堆栈帧。当函数返回时,堆栈帧将被销毁。如果递归调用函数,则每个递归级别都有自己的堆栈帧。例如,如果您有:
int factorial(int n) {
    if (n <= 1)
        return 1;
    else
        return factorial(n - 1) * n;
}

当您调用factorial(3)时,会创建一个堆栈帧,如下所示:
------------------------ stack pointer (SP)
n = 3
RA = <in main()>

当递归调用 factorial(2) 时,栈顶会添加一个额外的帧。
------------------------ SP
n = 2
RA = <in factorial()>
------------------------
n = 3
RA = <in main()>

另一个递归调用被执行,调用的是factorial(1)

------------------------ SP
n = 1
RA = <in factorial()>
------------------------
n = 2
RA = <in factorial()>
------------------------
n = 3
RA = <in main()>

这是递归的基本情况,返回值1被存储在寄存器中。函数调用完成后,顶部的栈帧被销毁,执行继续在保存的返回地址处。

------------------------ SP
n = 2                                      
RA = <in factorial()>
------------------------
n = 3
RA = <in main()>

现在,调用factorial(2)可以计算其返回值(2),然后销毁另一个堆栈帧:
------------------------ SP
n = 3
RA = <in main()>

最后,我们可以计算原始函数调用的结果(6),然后销毁该堆栈帧。

我想更正一下我的问题:在我第二个问题中所说的“成员函数”,我指的是“静态成员函数”。 - dev
堆栈帧对于静态成员函数和非静态成员函数的工作方式相同。唯一的区别在于this是否为局部变量之一。 - dan04

4
  1. 没有区别
  2. 本地变量在每次函数调用时都会在堆栈上被创建和销毁

如果函数本身只有1个副本,它如何在堆栈上有多个变量的副本? - dev
5
每次函数调用都会有一个对应的栈帧。 - dan04

2
  1. 我认为它们之间很可能没有区别。

  2. 看起来你应该多了解一下堆(heap)栈(stack)分配之间的区别。这可以让你在低层次上更好地理解内存是如何工作的,但仍然是相对高级的。很抱歉我现在无法提供更多帮助。

编辑:太慢了 :)


0
  1. 实际上它们之间没有太大的区别。两者都只存储在内存中一次,当调用非静态方法时,当前对象的指针(即this指针)会被推入堆栈(或根据编译器存储在ECX中),除此之外还有所有函数的参数。静态函数不需要类的实例,因此像普通的C函数一样调用即可。

  2. 与C语言相同,使用调用堆栈。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接