尾部递归是否需要return关键字?

时间:2019-03-02 22:06:43

标签: c++ recursion

我们正在学校学习递归。

根据我在网上阅读的内容,可以通过使递归步骤成为函数的最后一步来优化递归函数。

但是需要return关键字吗?甚至对于void函数?

void insert(Node<T>*& n, T value) 
{
    if (n == nullptr)
    {
        n = new Node<T>(value);
        return;
    }
    else if (value < n->get_value())
    {
        Node<T>* left = n->get_left();
        return insert(left, value);
    }
    else
    {
        Node<T>* right = n->get_right();
        return insert(right, value);
    }
}

如果没有return关键字,这仍然是尾递归吗?
特别是在else if中,因为没有它,它将“不再是函数要做的最后一件事”。

3 个答案:

答案 0 :(得分:2)

这些返回值在您的代码中没有执行任何操作。

只需删除一个“返回”即可;完全排成一行。

取消其他两行的返回。

我不是尾递归方面的专家,但我确实知道您的代码可以完成同样的事情,并且没有返回值也很简单。

答案 1 :(得分:2)

  

特别是在else中,如果没有它,它将“不再是函数要做的最后一件事”。

那是不正确的。

在所有情况下,insert调用都是 ,除非n == nullptr是函数执行的最后一项操作。

添加多余的return语句不会改变这一点。

此:

void bar() {}

void foo()
{
    return bar();
}

等效于此:

void bar() {}

void foo()
{
   bar();
   return;
}

或者这个:

void bar() {}

void foo()
{
   bar();
}

几乎所有方式。

实际上,我们完全允许 这样做的唯一原因是在返回void的函数中(请记住,您实际上并未在此处返回任何值!),是为了简化模板的实现。

而且,在所有这些示例中,编译器不需要为调用bar()设置新的堆栈框架。在使用递归函数的情况下,它可以为您提供 tail递归

答案 2 :(得分:2)

在您的代码中,所有三个return都不执行任何操作,可以将其删除。

如果函数返回void,则return仅用于 来提前终止函数。在您的代码中,所有这些return之后一无所有,因此它们是多余的。


另一方面,如果函数返回非void,则它有通过return(或异常或std::exit等终止) )。如果控制达到该函数的结尾},则行为是不确定的。

main()是此规则的例外,}的结尾main()自动达到return 0;


此外,正如@RetiredNinja所说,“ n必须是对指针的引用” 。否则,您对n所做的更改将被丢弃,并且通过new分配的内存将被泄漏。