超过矢量不会导致seg故障

时间:2015-09-30 02:48:30

标签: c++ vector segmentation-fault

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

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()并没有指向内部数组的末尾,而是指向最后一个被占用的单元格......好吧,这就是为什么迭代器减法的结果仍然是{在0之后{1}}。但是,为什么在填充一个单元格之后它仍然是reserve(1)。我期望0作为结果,因为1现在应该将迭代器返回到第二个内部数组单元格。 此外,为什么我在end()访问第十个单元格时没有遇到段错误,而向量只有1个单元长?

3 个答案:

答案 0 :(得分:4)

首先,end()为你提供了一个超出向量中最后一个元素的迭代器。如果向量为空,则begin()不能返回除{{1}}之外的其他内容。

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

最后,当你做

{{1}}

您正在索引向量越界,当您写入您不拥有的内存时,这会导致未定义的行为。 UB经常导致崩溃,但它没有,它可能似乎工作,而实际上它没有。

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

答案 1 :(得分:1)

这是猜测,但希望是有用的。

当您尝试访问尚未分配给进程内存空间的地址时,您将只获得段错误。当OS为程序提供内存时,通常以4KB为增量。因此,您可以在不触发段错误的情况下访问某些数组/向量的末尾,而不会触发其他段。

答案 2 :(得分:1)

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 []不同,此运算符从不将新元素插入容器中。

因此,假设向量具有足够的下标运算符元素。

顺便说一句:你在写v[9] = 0时应该怎么做?在将第10个元素设置为0之前,必须首先推送10个元素。以及如何设定自己的价值观?全部0?所以,它不会这样做,问题只取决于你自己。