Вы намеренно запутываете код, чтобы «заставить» компилятор создать конкретный результат;произойдет ли это или нет, вполне возможно, в большей степени зависит от используемого компилятора, действующих флагов оптимизации или даже от скомпилированного кода, использующего описанное выше.Ниже приведен более компактный код:
void Traversable::traverse(Traversable** prevNext)
{
bool doUpdate = update();
*prevNext = doUpdate ? this : next ? *prevNext : NULL;
Traversable **argNext = doUpdate ? &next : prevNext;
Traversable *localNext = next;
do_the_traversal_action(); // not spec'ed ...
if (!doUpdate)
delete this;
if (localNext)
localNext->traverse(argNext);
}
, который по-прежнему завершает функцию одной точкой возврата.Единственная причина, по которой он использует условные выражения, заключается в том, что вы меняете prevNext
там.
Edit: , что я пытаюсь сказать, это то, что независимо от того, как вы его кодируете, вВ конце концов, это зависит от компилятора, который решает, хочет ли он оптимизировать функцию или нет.Для современных оптимизирующих компиляторов часто есть переключатели (-fconserve-stack
или -foptimize-sibling-calls
в GCC), которые оказывают более непосредственное влияние на это, чем сам исходный код.
Редактировать 2: да, есликонечно, можно написать эту функцию не рекурсивно;все, в конце концов, это шаблон типа посетителя.Таким образом, фактическая активность заканчивается примерно так:
static void Traversable::traverse(Traversable *start)
{
Traversable *cur, *next;
for (cur = start; cur; cur = next) {
next = cur->next;
cur->do_the_traversal_action(); // not spec'ed ...
if (cur->update())
continue; // not supposed to remove this
if (next)
next->prevNext = cur->prevNext; // remove cur from list
delete cur;
}
}
Хотя, когда вы кодируете это так, следующий очевидный вопрос заключается в том, почему бы не реализовать простые типы итераторов для Traversable
и использовать std::remove_copy_if()
для задачи «приехать и удалить при условии».Или используйте список STL для начала.