我们正在学校学习递归。
根据我在网上阅读的内容,可以通过使递归步骤成为函数的最后一步来优化递归函数。
但是需要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
中,因为没有它,它将“不再是函数要做的最后一件事”。
答案 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
分配的内存将被泄漏。