在C++中使用递归的主要准则是什么?

What are the main guidelines for using recursion in C++?

本文关键字:是什么 C++ 递归      更新时间:2023-10-16

作为C++相对较新的,我想知道在使用递归时是否有具体的事情需要考虑,因为与Python,Java和/或函数式语言等语言相比,该语言的特殊性和低级性。

另外,我想知道各种编译器之间在如何处理递归(尤其是关于尾递归)方面是否存在许多差异。我目前在CodeBlocks和VS2010上与gcc合作。

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

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

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

有一些优化可以消除递归函数中的嵌套调用,但您的实现不应依赖于此行为,因为它不安全(例如,在更新编译器、更改构建设置或随着代码库的发展后,可能不再执行优化)。

您应该知道,大多数编译器/执行环境决定某些特定的堆栈大小 - 1MB 到 8MB 是非常典型的 - 根据我的经验C++运行时并不是为了动态增加它而设计的。 某些系统为程序代码启动的线程提供的堆栈可能比为操作系统启动的主线程提供的堆栈更少。 例如,在 Linux 上,您的 shell 可能允许您在运行应用程序之前使用 ulimit 来设置堆栈大小,但某些系统需要权限才能增加大小或可能有内核限制。

许多C++编译器在提供尾递归函数优化方面做得很好,因此内存使用量不会随着递归的深度而增长,但是当失败时,您可能会达到上述堆栈大小限制。

对于我使用的大多数语言(python,ruby,C,pascal等),这是非常典型的,并且C++对象往往非常小且内存效率高,因此您可能会比python中的等效数据和堆栈大小做得更好。

尽管如此,你还是提到了"函数式语言",它是如此开放,有些是如此"实验性",我敢打赌,有些人实际上为递归动态分配"堆"内存,并且可以远远超出C++实现倾向于支持的范围。 某些在虚拟机上运行/解释字节代码的语言也可能这样做。

我会注意递归函数中使用的任何指针、指针到指针等,以防您发现自己站在自己的尾巴上。