C++ 堆栈和作用域

标签 c++ optimization stack

我在 Visual C++ 2008 上试过这段代码,它显示 A 和 B 没有相同的地址。

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

    int B;
    printf("%p\n", &B);
}

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

我不明白为什么编译器似乎没有做看起来非常简单的优化(例如,这在较大变量和递归函数的上下文中可能很重要)。而且似乎重用它不会增加 CPU 和内存的负担。有人对此有解释吗?

我猜答案是“因为它比看起来复杂得多”,但老实说我不知道​​。

编辑:关于以下答案和评论的一些精确度。

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

我建议的是内存优化,但我看不出它会如何损害性能。

顺便说一句,这发生在发布 版本中,所有优化都会开启。

最佳答案

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

由于多种原因,您可能看不到这种优化。

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

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

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

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

关于C++ 堆栈和作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1343190/

相关文章:

c++ - 生命游戏,C++ - 多态数组(也许还有指针)

python - 在 Python 中快速检查范围

python - 将一个大长方体切割成尺寸在一定范围内的随机小长方体

c - 如何破坏 C 程序中的堆栈

c++ - Conan.io - 是否可以做类似于 "python setup.py develop"的事情?

使用模板的 C++ 链表

c++ - 继承和静态变量

future 框架版本中的 C# 抖动改进

c - MIPS的堆栈让我脑洞大开

c - 全局变量被破坏