C++堆栈和范围

Dre*_*mer 8 c++ optimization stack

我在Visual C++ 2008上尝试了这个代码,它显示A和B没有相同的地址.

int main()
{
    {
        int A;
        printf("%p\n", &A);
    }

    int B;
    printf("%p\n", &B);
}
Run Code Online (Sandbox Code Playgroud)

但是当B被定义时A不再存在,在我看来,相同的堆栈位置可以重用...

我不明白为什么编译器看起来不像一个非常简单的优化(例如在较大的变量和递归函数的上下文中可能很重要).并且似乎重用它不会在CPU和内存上更重.有没有人对此有解释?

我想答案是"因为它比它看起来要复杂得多",但老实说我不知道​​.

编辑:关于以下答案和评论的一些准确性.

这段代码的问题在于,每次调用此函数时,堆栈都会"增加一个整数".当然,这在示例中没有问题,但考虑大变量和递归调用,并且您可以轻松避免堆栈溢出.

我建议的是内存优化,但我不知道它会如何损害性能.

顺便说一句,这种情况发生在发布版本中,将进行所有优化.

Mic*_*ael 8

为这样的本地人重用堆栈空间是一种非常常见的优化.事实上,在优化的构建中,如果你没有获取本地的地址,编译器甚至可能不会分配堆栈空间,变量只会存在于寄存器中.

由于多种原因,您可能看不到此优化.

首先,如果优化已关闭(如调试版本),编译器将不会执行其中任何一项以使调试更容易 - 您可以查看A的值,即使它不再在函数中使用.

如果您正在使用优化进行编译,我的猜测是,因为您正在获取本地的地址并将其传递给另一个函数,编译器不希望重用该存储,因为它不清楚该函数对该地址的作用.

还可以设想一个不使用此优化的编译器,除非函数使用的堆栈空间超过某个阈值.我不知道有任何编译器这样做,因为重用不再使用的局部变量空间没有成本,可以全面应用.

如果堆栈增长是您的应用程序的一个严重问题,即在某些情况下您遇到堆栈溢出,您不应该依赖编译器的堆栈空间优化.您应该考虑将堆栈上的大缓冲区移动到堆上,并努力消除非常深的递归.例如,在Windows上,线程默认具有1 MB堆栈.如果你担心溢出,因为你在每个堆栈帧上分配1k内存并进行1000次递归调用,修复不是试图诱使编译器从每个堆栈帧中节省一些空间.