这可以优化尾部调用吗?如果是这样,它没有发生的特殊原因是什么?

Can this be tail call optimized? If so, what's the special reason for it not happen?

本文关键字:是什么 尾部 优化 调用 如果      更新时间:2023-10-16

我已经使用 gcc 4.8.1 和 clang 3.4.190255 在许多优化级别检查了程序集输出,没有针对此类代码的尾部调用优化。

collatz_aux没有得到尾部调用优化的任何特殊原因?

#include <vector>
#include <cassert>
using namespace std;
vector<unsigned> concat(vector<unsigned> v, unsigned n) {
    v.push_back(n);
    return v;
}
vector<unsigned> collatz_aux(unsigned n, vector<unsigned> result) {
    return n == 1
        ? result
        : n % 2 == 0
            ? collatz_aux(n / 2, concat(move(result), n))
            : collatz_aux(3 * n + 1, concat(move(result), n));
}
vector<unsigned> collatz_vec(unsigned n) {
    assert(n != 0);
    return collatz_aux(n, {});
}
int main() {
    return collatz_vec(10).size();
}

vector<unsigned>参数的析构函数需要在返回后调用。

仅供参考,我调整了递归版本,以获得尾递归,如下所示:

#include <vector>
#include <cassert>
using namespace std;
template<class container>
container &&collatz_aux(unsigned n, container &&result) {
    static auto concat = [](container &&c, unsigned n) -> container &&{
        c.push_back(n);
        return forward<container>(c);
    };
    return n == 1
        ? forward<container>(result)
        : n % 2 == 0
            ? collatz_aux(n / 2, concat(forward<container>(result), n))
            : collatz_aux(3 * n + 1, concat(forward<container>(result), n));
}
vector<unsigned> collatz_vec(unsigned n) {
    assert(n != 0);
    return collatz_aux(n, vector<unsigned>{});
}
int main() {
    return collatz_vec(10).size();
}

你不应该依赖尾声来做这件事。我认为优化器不太可能发现两个递归调用都可以进行尾部优化。

这是一个非递归版本。

vector<unsigned> collatz_aux(unsigned n, vector<unsigned> result) {
  while(true){
    if(n == 1) return result;
    result = concat(move(result), n);
    if(n % 2 == 0)
    {
      n=n / 2;
    }else{
      n= 3 * n + 1;
    }
  }
}