Поддержка Tail Call Optimization (TCO) ограничена в C / C ++.
Поэтому, если код использует TCO, чтобы избежать переполнения стека, может быть лучше переписать его с помощью цикла.В противном случае необходим некоторый автоматический тест, чтобы убедиться, что код оптимизирован.
Обычно TCO может быть подавлен:
Здесь TCO путается, возвращая структуру по значению.Это можно исправить, если результат всех рекурсивных вызовов будет записан на один и тот же адрес памяти, выделенный в другой функции twoSum
(аналогично ответу https://stackoverflow.com/a/30090390/4023446 на Хвост-рекурсия не происходит )
struct result
{
int i;
int j;
bool found;
};
struct result gen_Result(int i, int j, bool found)
{
struct result r;
r.i = i;
r.j = j;
r.found = found;
return r;
}
struct result* twoSum_Helper(int numbers[], int size, int target,
int i, int j, struct result* res_)
{
if (i >= (size - 1)) {
*res_ = gen_Result(i, j, false);
return res_;
}
if (numbers[i] + numbers[j] == target) {
*res_ = gen_Result(i, j, true);
return res_;
}
if (j >= size)
return twoSum_Helper(numbers, size, target, i + 1, i + 2, res_);
else
return twoSum_Helper(numbers, size, target, i, j + 1, res_);
}
// Return 2 indexes from numbers that sum up to target.
struct result twoSum(int numbers[], int size, int target)
{
struct result r;
return *twoSum_Helper(numbers, size, target, 0, 1, &r);
}
Значение указателя res_
является постоянным для всех рекурсивных вызовов twoSum_Helper
.Из результатов сборки (флаг -S) видно, что хвостовая рекурсия twoSum_Helper
оптимизирована как цикл даже с двумя рекурсивными точками выхода.
Параметры компиляции: g ++ -O2 -S (версия g ++4.7.2).