相对较新的C ++我想知道在使用递归时是否有特定的事情需要考虑因为与Python,Java和/或函数式语言等语言相比语言的特定性和低级别。
另外,我想知道各种编译器在处理递归方面是否存在很多差异(特别是关于尾递归)。我目前在CodeBlocks和VS2010上使用gcc。
答案 0 :(得分:5)
C ++中的递归应该绑定,而不是非常深入 - 特别是当您的实现能够创建非常重要的堆栈分配时。如果您的程序不符合这些要求,那么您应该采用另一种方法(例如迭代)。
每个函数调用都需要一些堆栈存储,并且您的函数参数也需要堆栈存储。您获得多少堆栈存储取决于您的实现/环境。现代桌面系统通常不会给你超过几MB。其他实现将为您提供更少的功能。
如果您的调用超出了线程堆栈的边界,那么您将获得堆栈溢出。
有一些优化可以消除递归函数中的嵌套调用,但是您的实现不应该依赖于此行为,因为它不安全(例如,在更新编译器,更改构建设置或者更改构建设置后,可能不再执行优化)随着你的代码库不断发展)。
答案 1 :(得分:3)
你应该知道大多数编译器/执行环境都决定了一些特定的堆栈大小--1MB到8MB是非常典型的 - 而且根据我的经验,C ++运行时并不是为了动态地增加它而设计的。对于由程序代码启动的线程,某些系统可能比为OS启动的主线程提供更少的堆栈。在Linux上 - 例如 - 您的shell可能允许您在运行应用程序之前使用ulimit
设置堆栈大小,但某些系统需要特权来增大大小或可能具有内核限制。
许多C ++编译器在提供tail recursive function optimisations方面表现相当不错,因此内存使用量不会随着递归的深度而增长,但是当失败时,您可能会达到上面提到的堆栈大小限制。
对于我使用过的大多数语言(python,ruby,C,pascal等)来说,这是非常典型的,而且C ++对象往往非常简单且内存效率很高,所以你可能比同等数据和堆栈大小,比方说python。
尽管如此,你提到的“功能语言”是如此开放式的,有些是如此“实验性的”我敢打赌,有些人实际上会为递归动态分配“堆”内存,并且可以超越C ++实现所支持的范围。在虚拟机上运行/解释字节代码的某些语言也可以这样做。
答案 2 :(得分:0)
我会注意你的递归函数中使用的任何指针,指针指针等,以防你发现自己站在自己的尾巴上。