在我看来,在 C 和 C++ 中进行尾递归优化都可以很好地工作,但在调试时我似乎从未看到表明这种优化的帧堆栈。这很好,因为堆栈告诉我递归的深度。不过,优化也会很好。
有 C++ 编译器进行此优化吗?为什么?为什么不?
我该如何告诉编译器去做呢?
- 对于 MSVC:
/O2
or /Ox
- 对于海湾合作委员会:
-O2
or -O3
如何检查编译器在某种情况下是否执行了此操作?
- 对于 MSVC,启用 PDB 输出以便能够跟踪代码,然后检查代码
- 对于海湾合作委员会..?
我仍然会接受有关如何确定编译器是否像这样优化某个函数的建议(尽管康拉德告诉我假设它让我放心)
总是可以通过进行无限递归并检查它是否导致无限循环或堆栈溢出来检查编译器是否执行此操作(我使用 GCC 执行此操作并发现-O2
就足够了),但我希望能够检查某个我知道无论如何都会终止的函数。我很想有一个简单的方法来检查这个:)
经过一些测试,我发现析构函数破坏了进行此优化的可能性。有时,更改某些变量和临时变量的范围以确保它们在返回语句开始之前超出范围是值得的。
如果尾部调用后需要运行任何析构函数,则无法进行尾部调用优化。
目前所有主流编译器都进行尾调用优化相当好(并且已经这样做了十多年),即使对于相互递归调用 https://godbolt.org/g/TjqTHV例如:
int bar(int, int);
int foo(int n, int acc) {
return (n == 0) ? acc : bar(n - 1, acc + 2);
}
int bar(int n, int acc) {
return (n == 0) ? acc : foo(n - 1, acc + 1);
}
让编译器进行优化很简单:只需打开速度优化即可:
- 对于 MSVC,请使用
/O2
or /Ox
.
- 对于 GCC、Clang 和 ICC,请使用
-O3
检查编译器是否进行优化的一个简单方法是执行一个调用,否则会导致堆栈溢出 - 或者查看汇编输出。
作为一个有趣的历史记录,C 的尾部调用优化是在 GCC 的过程中添加的。学位论文 http://www.complang.tuwien.ac.at/schani/diplarb.ps作者:马克·普罗布斯特。本文描述了实施过程中的一些有趣的注意事项。值得一读。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)