超过矢量不会引起区段故障

exceeding vector does not cause seg fault

本文关键字:段故障 故障 起区      更新时间:2023-10-16

我对这段代码的结果感到非常困惑:

std::vector<int> v;
std::cout << (v.end() - v.begin()) << std::endl;
v.reserve(1);
std::cout << (v.end() - v.begin()) << std::endl;
v[9] = 0;
std::cout << (v.end() - v.begin()) << std::endl;
输出:

0
0
0

所以…首先……end()不指向内部数组的末端,而是指向最后一个被占用的cell…这就是为什么迭代器的减法结果在reserve(1)之后仍然是0。但是,为什么一个细胞被填满后仍然是0。我期望结果是1,因为end()现在应该将迭代器返回到第二个内部数组单元格。此外,为什么在地球上我没有得到一个segfault访问第十个细胞与v[9] = 0,而矢量只有1个细胞长?

首先,end()为您提供了指向vector中最后一个元素之后的迭代器。如果vector为空,则begin()只能返回与end()相同的值。

当你调用reserve()时,你实际上并没有创建任何元素,你只是保留了一些内存,这样当你添加元素时,向量就不必重新分配了。

最后,当你做

v[9] = 0;

您正在索引向量超出边界,这导致未定义行为当您写入不属于您的内存时。UB经常导致崩溃,但它没有,它可能看起来工作,而实际上它不起作用。

作为最后一部分的注释,[]运算符没有边界检查,这就是为什么它会接受超出边界的索引。如果你想要边界检查,你应该使用at()

v[9] = 0;,你只是访问了边界外的向量,它是UB。它在某些情况下可能会崩溃,也可能不会。

v[9] = 0;,你根本不添加元素。您需要使用push_backresize:

v.push_back(0); // now it has 1 element
v.resize(10);   // now it has 10 elements

编辑

为什么v[index]没有创建一个元素?

因为std::vector::operator[]不能做到这一点

返回对指定位置pos的元素的引用。不执行边界检查。与std::map::operator[]不同,此操作符从不向容器中插入新元素。

因此假定该向量有足够的元素来进行下标操作。

BTW:当你写v[9] = 0时,你认为vector应该做什么?在将第10个元素设置为0之前,它必须先压入10个元素。如何设定他们的价值观?所有0 ?所以,它不会这样做,问题只是取决于你自己。

这是一个猜测,但希望对您有所帮助。

当你试图访问一个没有分配给进程内存空间的地址时,你只会得到一个段错误。当操作系统为程序提供内存时,它通常以4KB为增量。因此,您可以访问超过结尾的一些数组/向量而不会触发段错误,但不能访问其他的。