【问题标题】:Tail call optimization besides tail recursion?除了尾递归之外的尾调用优化?
【发布时间】:2013-08-04 20:42:31
【问题描述】:

除了尾递归之外,是否还有其他可能的尾调用优化?我一直在尝试寻找或想到一个不涉及递归但没有成功的方法。可能吗?有什么例子吗?

【问题讨论】:

标签: c++ c optimization compiler-construction tail-call-optimization


【解决方案1】:

当然,“尾调用优化”实际上是这种优化的最通用术语,与递归无关。这种优化不会用 while 循环或类似的东西代替递归。相反,尾调用被转换,使得调用者的堆栈帧被重新使用。 return f(...)f(...); return 形式的任何代码都可以对此进行修改。它适用于 any f,甚至适用于编译器不可能知道正在调用什么的函数指针/闭包/虚拟方法。因此,它还可以更好地用于单独编译、高阶函数、后期绑定等。

如果您查看了足够多的代码,无论是函数式的还是命令式的,您都会发现偶尔会出现没有任何后续调用的调用。一个常见的情况是调用者将主要任务委托给被调用者,并且只做一些额外的准备工作。在函数式代码中,您经常会发现许多只做一件事并根据其他小函数实现的小函数,因此您最终需要对参数应用简单的转换,然后执行尾调用下一层(以转换后的数据为参数)。 TCO 优化了第二步,它(理想情况下)使调用与简单的jump 一样便宜,并使漂亮的模块化代码与更单一的实现相比占用更少的堆栈空间。在面向对象的设计中,您可能希望组合其他对象的对象并公开委托的便捷方法:

SomeClass doSomething(Argument a) {
    log.debug("Doing something");
    return this.somethingDoer.doIt(a, this.someExtraData);
}

另一个在技术上相互递归的示例,但通常只有很少的任何给定函数的激活(中间有数十或数百个其他激活),是通过每个状态具有一个函数并调用它进入该状态来实现的状态机:

void stateA() {
    // do actual work
    // determine which transition applies
    stateB();
}

void stateB() {
    // do actual work
    // determine which transition applies
    state...();
}

// dozens, possibly hundreds of other states

【讨论】:

    【解决方案2】:
    int bar(int x);
    int foo(int x) { return bar(x); }
    

    foo 可以直接跳转到bar 直接返回给调用者;任何地方都不需要递归。

    【讨论】:

    • @ddriver:我刚刚取出了bar的定义,只留下了它的声明。你不能在没有定义的情况下内联bar,但你可以对其调用者执行尾调用优化。看出区别了吗?
    • 这实际上是一对可能相互递归的函数的一半......
    • @H2CO3:呃什么?尾调用优化不关心这些是否相互递归......
    • @Mehrdad 我知道,这不是我的意思......只是分裂头发。 OP 要求没有递归的东西。
    猜你喜欢
    • 2021-05-30
    • 2018-03-08
    • 1970-01-01
    • 2014-06-23
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-03
    相关资源
    最近更新 更多