C++ 递归有限制吗?
我正在测试递归,但是当我有一个超过150000个元素的数组时,就会出现分割错误。有什么问题吗C++ 递归有限制吗?,c++,C++,我正在测试递归,但是当我有一个超过150000个元素的数组时,就会出现分割错误。有什么问题吗 #include <iostream> using namespace std; void init ( float a[] , long int n ); float standard ( float a[] , long int n , long int i ); int main() { long int n = 1000000; float *a = new
#include <iostream>
using namespace std;
void init ( float a[] , long int n );
float standard ( float a[] , long int n , long int i );
int main()
{
long int n = 1000000;
float *a = new float[n];
init ( a , n );
cout.precision ( 30 );
cout << "I got here." << endl;
cout << "Standard sum= " << standard ( a , 0 , n - 1 ) << endl;
delete [] a;
return 0;
}
void init ( float a[] , long int n )
{
for (long int i = 0 ; i < n ; i++ )
{
a[i] = 1. / ( i + 1. );
}
}
float standard ( float a[] , long int i , long int n )
{
if ( i <= n )
return a[i] + standard ( a , i + 1 , n );
return 0;
}
#包括
使用名称空间std;
void init(float a[],long int n);
浮动标准(浮动a[],长整数n,长整数i);
int main()
{
长整数n=1000000;
浮动*a=新浮动[n];
init(a,n);
计算精度(30);
cout可能堆上的内存不足。此外,如果得到16位int,则迭代可能有问题。最好使用int32_t i而不是int i。与n相同。可能堆上的内存不足。如果得到16位int,则迭代可能有问题。最好使用int32_t i而不是int i。与n相同。递归函数standard
(其递归深度为n
)中的堆栈空间很可能用完,此处可能未启用尾部调用优化
因此,为了回答标题中的问题:是的,递归有一个限制,通常是可用的堆栈空间。您的递归函数标准中的堆栈空间很可能已经用完,该函数递归深度为n
,这里可能没有启用尾部调用优化
因此,为了回答标题中的问题:是的,递归有一个限制,通常是可用的堆栈空间。作为MicroVirus正确答案的扩展,下面是一个算法尾部递归版本的示例:
float standard_recursion(float* a, long i, long n, long result) {
if(i > n)
return result;
return standard_recursion(a, i + 1, n, result + a[i]);
}
float standard(float* a, long i, long n ) {
return standard_recursion(a, i, n, 0);
}
如果编译器进行尾部调用优化(我在g++-O2上测试过),则应该运行该命令。但是,由于功能取决于编译器优化,我建议完全避免深度递归,并选择迭代解决方案。作为对MicroVirus正确答案的扩展,下面是您算法的尾部递归版本示例:
float standard_recursion(float* a, long i, long n, long result) {
if(i > n)
return result;
return standard_recursion(a, i + 1, n, result + a[i]);
}
float standard(float* a, long i, long n ) {
return standard_recursion(a, i, n, 0);
}
如果编译器进行尾部调用优化(我在g++-O2上进行了测试),则应该运行此功能。但是,由于功能取决于编译器优化,我建议完全避免深度递归,并选择迭代解决方案。是的,它是,这是我传递到那里的指针。我误读了,对不起,我认为你的意思是“递归”而不是“回溯”。在任何情况下,trhat闻起来更多的是堆栈溢出而不是分段错误。我得到了以下结果:我到了这里。分段错误(内核转储)
是的,它是一个指针,我传递到那里。我读错了,对不起,我认为你的意思是“递归”而不是“回溯”。在任何情况下,trhat闻起来更多的是堆栈溢出,而不是分段错误。我得到了以下结果:我在这里得到了。分段错误(内核转储)
我怀疑他正在耗尽堆空间。150000个浮点大约是半兆字节。没有理由在这里使用显式位大小类型(即int32\u t
):请坚持使用int,否则会持续很长时间,除非类型的宽度需要固定到某个精确的数字。@user2079303:它不会是150000个浮点数。它将是150000个堆栈帧-所有局部变量的总和+返回点OK。我现在明白了。这个答案是一个部分答案,应该用MicroVirus的答案来读取。@LokiAstari是的,那些堆栈帧可能会消耗更多内存。但可能不足以填满堆。但顾名思义,堆栈帧存储在堆栈上,而这正是他耗尽内存的地方——而不是在堆上。最大堆栈大小不会根据使用情况而增长,它的限制是在编译时设置的。我怀疑他是否耗尽了堆空间。150000个浮点数是必要的大约半兆字节。没有理由在这里使用显式位大小类型(即int32\t
):请坚持使用int,否则会持续很长时间,除非类型的宽度需要固定到某个精确的数字。@user2079303:它不会是150000个浮点数。它将是150000个堆栈帧-所有局部变量的总和+返回点OK。我现在明白了。这个答案是一个部分答案,应该用MicroVirus的答案来读取。@LokiAstari是的,那些堆栈帧可能会消耗更多内存。但可能不足以填满堆。但顾名思义,堆栈帧存储在堆栈上,而这正是他耗尽内存的地方——而不是在堆上。最大堆栈大小不会根据使用情况而增长,它的限制是在编译时设置的。