如果有的话,C++编译器做尾递归优化?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (26)

在我看来,它可以非常好地在C和C ++中进行尾递归优化,但在调试时我似乎没有看到指示此优化的帧堆栈。这很好,因为堆栈告诉我递归有多深。不过,优化也会很好。

是否有任何C ++编译器会做这种优化?为什么?为什么不?

我该如何去告诉编译器来做到这一点?

  • 对于MSVC:/ O2或/ Ox
  • 对于GCC:-O2或-O3

如何检查编译器是否在特定情况下完成了这项工作?

  • 对于MSVC,启用PDB输出以便能够跟踪代码,然后检查代码
  • 对于GCC ..?

我仍然会对如何确定某个函数是否由编译器进行优化提供建议(即使我发现康拉德让我承认它)

总是可以通过无限递归检查编译器是否执行此操作,并检查它是否导致无限循环或堆栈溢出(我使用GCC进行了此操作并发现-O2已足够),但我想要能够检查某个我知道会终止的函数。我很想有一个简单的方法来检查这:)

经过一些测试后,我发现破坏者破坏了进行此优化的可能性。有时可能需要更改某些变量和临时对象的范围,以确保它们在返回语句开始之前超出范围。

如果在尾部呼叫后需要运行任何析构函数,则不能进行尾部呼叫优化。

提问于
用户回答回答于

当前版本的VC ++和GCC都相当好地调用了优化,甚至用于相互递归调用。我敢打赌英特尔编译器也是。

让编译器进行优化很简单:只需打开优化速度即可。

  • 对于MSVC,请使用/ O2或/ Ox。
  • 对于GCC,使用-O3

检查编译器是否执行了优化(我知道)的最简单方法是执行调用,否则会导致堆栈溢出 - 或者查看程序集输出。但是,你通常不会假设编译器进行了优化。

用户回答回答于

gcc 4.3.2完全将这个函数纳入main()。优化级别是-O1。我注意到,即使将它static改为extern,尾递归也会很快消失,所以我不会依赖它来保证程序的正确性。

#include <stdio.h>
static int atoi(const char *str, int n)
{
    if (str == 0 || *str == 0)
        return n;
    return atoi(str+1, n*10 + *str-'0');
}
int main(int argc, char **argv)
{
    for (int i = 1; i != argc; ++i)
        printf("%s -> %d\n", argv[i], atoi(argv[i], 0));
    return 0;
}

扫码关注云+社区