【发布时间】:2018-08-30 00:58:55
【问题描述】:
如果 bar 调用 bar(i/2),如果 i 是偶数,否则 bar(3*i + 1),递归函数 bar 将进行尾递归。
const int bar(const int i)
{
if (i < 2) return i;
return i % 2 ? bar(i/2) : bar(3*i + 1);
}
但是,如果 bar 调用 bar 或 foo,而后者的局部变量集与 bar 完全不同,该怎么办?
const int bar(const int i)
{
if (i < 2) return i;
return i % 2 ? bar(i/2) : foo(3*i + 1);
// where foo is very complicated recursive call that has
// 11 different user-defined/primitive type of
// local variables that can't be optimized out
}
我的理解是尾递归优化将使用调用者的堆栈。调用者在调用被调用者之前已经完成了它的局部变量。因此,被调用者可以重用它。当调用者和被调用者是同一个函数时(例如 foo 调用 foo,bar 调用 bar),我的理解听起来不错。但是,如果堆栈大小和布局完全不同,并且被调用者可能是具有不同堆栈布局的多个不同函数之一,会发生什么?
首先,它会是尾递归吗? (现在,我知道可能会应用尾部“调用”优化,但不是这不是尾部“递归”。)其次,主要的编译器,如 gcc、clang 等,会优化这种尾部调用吗? (答案似乎是的。)
如果被调用者(第二个代码示例中的 foo)要复杂得多怎么办?如果被调用者和调用者相互调用(相互递归),我的第二个代码示例中的调用是否会进行尾调用优化?如果被调用者(例如 foo)是一个复杂的递归调用,绝对不是尾递归,并且编译器很难将其减少为循环左右,它是否仍然是尾调用优化的?
【问题讨论】:
-
无论 foo() 做什么都对 bar() 没有影响。如果编译器可以优化 bar() 以进行尾递归,则它(至少在您的场景中)不必担心 foo()。假设您调用了 printf() - 这会阻止尾递归优化吗?
-
从
bar()调用foo()不是递归。所以我看不到相关性。 -
你说的优化是“尾调用优化”。尽管它在(相互)递归中最有用,但绝不限于这种情况。
-
@CraigYoung 了解mutual recursion
-
@naomik 该问题未能在其“最小示例”中演示相互递归。 (关于
foo()的虚张声势的虚张声势的阐述并不能代替演示。)那么:你的意思是什么? OP 没有用foo()演示任何类型的递归。所以我仍然没有看到相关性。
标签: c++ c recursion tail-recursion