我正在练习一个数组操作问题。在求解时,我声明了一个数组(代码中的数组 A(。 对于某些测试用例,我遇到了分段错误。我用矢量替换了数组并得到了 AC。我不知道这是什么原因。请解释一下。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,m,a,b,k;
cin>>n>>m;
vector<long int> A(n+2);
//long int A[n+2]={0};
for(int i=0;i<m;i++)
{
cin>>a>>b>>k;
A[a]+=k;
A[b+1]-=k;
}
long res=0;
for(int i=1;i<n+2;i++)
{
A[i]+=A[i-1];
if(res<A[i])
res=A[i];
}
cout<<res;
return 0;
}
由于看起来您已经很长时间没有在C++编程了,我将尝试为您分解它以使其更易于理解: 首先,c ++不会为您初始化任何值,这不是Java,所以请不要这样做:
int n,m,a,b,k;
然后使用:
A[a]+=k;
A[b+1]-=k;
在这一点上,我们不知道 a 和 b 是什么,据我们所知,它可能是 -300,你从未初始化过它。因此,偶尔你会很幸运,编译器启动的数字不会导致分段错误,而其他时候你没有那么幸运,编译器初始化的值确实会导致分段错误。
long int A[n+2]={0};
在标准C++中是不合法的。这有很多原因,我想你偶然发现了其中一个。
允许可变长度数组的编译器遵循 C99 的示例,并将数组分配给堆栈。堆栈是有限的资源,对于台式计算机,通常在 1 到 10 MB 之间。如果用户输入足够大小的n
,数组将占用过多的堆栈或超出堆栈的边界,从而导致未定义的行为。然后,这种行为表现为访问内存的分段错误,该内存远离堆栈的末端,以至于不受程序控制。堆栈溢出时通常不会发出警告。通常,程序崩溃或数据损坏是您发现的方式,到那时挽救程序为时已晚。
另一方面,vector
从自由存储中分配其内部缓冲区,并且在具有虚拟内存和 64 位寻址的现代 PC 上,免费存储非常大,如果您尝试超出它可以分配的范围,则会引发异常。
另一个重要的区别是
long int A[n+2]={0};
可能没有将数组初始化为零。g++ 就是这种情况。第一个字节将设置为零,其余字节未初始化。这就是使用非标准扩展的诅咒。您不能指望标准所保证的行为。
std::vector
将初始化整个数组或将数组设置为您告诉它使用的任何值。