我已经使用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();
}
答案 0 :(得分:12)
返回后需要调用vector<unsigned>
参数的析构函数。
答案 1 :(得分:2)
仅供参考,我调整了递归版本,以获得尾递归,对此:
#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();
}
答案 2 :(得分:1)
你不应该依赖尾调。我认为优化器不太可能发现两个递归调用都可以进行尾部优化。
这是一个非递归版本。
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;
}
}
}