在C++;? C++相对较新,我想知道在使用递归时是否有特定的事情要考虑,因为语言的特殊性和低水平性与Python、java和/或函数语言等语言相比。

在C++;? C++相对较新,我想知道在使用递归时是否有特定的事情要考虑,因为语言的特殊性和低水平性与Python、java和/或函数语言等语言相比。,c++,recursion,C++,Recursion,另外,我想知道不同的编译器在如何处理递归(特别是关于尾部递归)方面是否有很多不同之处。我目前在GCC上使用CODBoLD和VS2010。 < P>递归在C++中应该被绑定,而不是下降得非常深——尤其是当你的实现能够创建非平凡的堆栈分配时。如果您的程序不满足这些要求,那么您应该采用另一种方法(例如迭代) 每个函数调用都需要一些堆栈存储,函数参数也需要堆栈存储。您获得的堆栈存储量取决于您的实现/环境。现代桌面系统一般不会给你超过几MB的空间。其他实现将为您提供更少的资源 如果调用超出了线程堆栈的边界

另外,我想知道不同的编译器在如何处理递归(特别是关于尾部递归)方面是否有很多不同之处。我目前在GCC上使用CODBoLD和VS2010。

< P>递归在C++中应该被绑定,而不是下降得非常深——尤其是当你的实现能够创建非平凡的堆栈分配时。如果您的程序不满足这些要求,那么您应该采用另一种方法(例如迭代)

每个函数调用都需要一些堆栈存储,函数参数也需要堆栈存储。您获得的堆栈存储量取决于您的实现/环境。现代桌面系统一般不会给你超过几MB的空间。其他实现将为您提供更少的资源

如果调用超出了线程堆栈的边界,则会出现堆栈溢出


有一些优化可以消除递归函数中的嵌套调用,但您的实现不应该依赖于此行为,因为它是不安全的(例如,在更新编译器、更改生成设置或随着代码库的发展,可能不再执行此优化)你应该知道大多数编译器/执行环境决定了某些特定的堆栈大小——1MB到8MB是非常典型的,而C++运行时不是我的经验,而是为了动态地增加。一些系统可能为程序代码启动的线程提供的堆栈比为操作系统启动的主线程提供的堆栈更少。例如,在Linux上,您的shell可能允许您在运行应用程序之前使用设置堆栈大小,但有些系统需要权限来增加堆栈大小,或者可能有内核限制

< >许多C++编译器在提供内存方面做得很好,所以内存使用不会随着递归深度的增长而增加,但是当失败时,你可能会碰到上面提到的栈大小限制。

这对于我使用过的大多数语言来说是非常典型的(Python、Ruby、C、Pascal等),C++对象往往非常小,内存效率高,所以在Python中,你可能比用等效的数据和堆栈大小做得更好。


你还提到了“功能语言”,它是开放式的,有些是“实验性的”,我敢打赌,有些人实际上为“递归”动态分配“堆”内存,并且可以超越C++实现的支持方式。一些在虚拟机上运行/解释字节码的语言可能也会这样做。

我会注意递归函数中使用的任何指针、指向指针的指针等,如果你发现自己站在你自己的尾巴上。

递归在C++中使用,就像在任何其他编程语言中或在任何其他地方或城市中一样…如果你期望尾调用优化,一个鬼鬼祟祟的陷阱就是析构函数。如果有任何析构函数需要作为离开函数的一部分运行,那么它们必须在任何被调用函数返回后运行;这破坏了尾部调用优化的可能性。您可以通过引入在
return
-语句之前结束的其他显式作用域来限制对象的生存期。@nbro:不,某些编程语言保证尾部调用优化。这就产生了巨大的差异。经验法则:
O(logn)
递归深度正常,
O(N)
不正常,
O(sqrt(N))
可能不正常。@MSalters或者
N
是一个已知的小数字,可能是常数。我在考虑回溯算法,比如8皇后问题,或者解决数独问题。递归深度显然是
O(N)
,但是
N
是一个已知的相对较小的常数(8皇后问题为8,数独问题为81)。我不想尝试在不使用递归的情况下解决回溯问题。@JamesKanze:总是存在定义
N
的问题。例如,在8皇后问题中,每8行中有8个可能的位置,因此您可以考虑8 ^ 8个可能的位置。回溯算法基本上就是O(log(8^8))的解决方案。@m 8个皇后问题的替代方案:只有8列,每列最多一个皇后,因此回溯是:在当前列中为皇后选择一个位置,然后递归到下一列。所以
N
这里是列数。@JamesKanze:我知道这个谜题就是“把8个皇后放在一个棋盘上,这样他们就不会互相攻击”,从技术上讲,这是一个
64的搜索空间!/(56!*8!)
位置。
N
的定义取决于您得出解决方案的方向。