2

考虑:

#include <vector>

int main()
{
  std::vector <int> v;
  v.reserve (100);
  v[1] = 42;
}

我知道上面的代码调用了未定义的行为,因为在调用站点 for v[1],向量的大小根据v.size()是 < 1。(它是零。)

但是,我花了大约最后一个小时来查看 C++ 标准中的引文,该引文直接或间接地阐明了这实际上是未定义的行为。

也许我错过了显而易见的事情。您能否提供至少来自 C++03 和可选的 C++11 标准的引文或引文来澄清这一点?

4

3 回答 3

11

operator[]这是如何定义的产物。在 §23.2.3 [sequence.rqmts] 表 101 中,操作语义operator[]定义为*(a.begin() + n). 所以它是根据迭代器定义的。根据§24.2.1/5 [iterator.requirements.general] ,增加begin过去和取消引用它是未定义的行为。end

于 2013-07-18T18:30:19.653 回答
1

这不能回答您的基本问题,但是您的向量不是大小为 0,而是大小为 100(因为您使用 size 构造函数创建了它)

手册页std::vector确实声称它是未定义的行为,但我不知道您是否认为这“足够好”(您要求引用 c++ 标准)

template<typename _Tp, typename _Alloc = std::allocator<_Tp>> reference std::vector< _Tp, _Alloc >::operator[] (size_type__n)
   [inline]
   Subscript access to the data contained in the vector. Parameters:
       n The index of the element for which data should be accessed.

   Returns:
       Read/write reference to data.

   This operator allows for easy, array-style, data access. Note that data access with this operator is unchecked and
   out_of_range lookups are not defined. (For checked lookups see at().)

   Definition at line 695 of file stl_vector.h.
于 2013-07-18T18:29:59.523 回答
0

a[n](其中a是一个向量并且n是一个整数)在 23.2.3p16 的表 101 中定义为*(a.begin() + n).

23.3.6.1p1 说“向量...支持随机访问迭代器”。24.2.7p1 中的表 111 根据 定义a + n(其中a是随机访问迭代器)a += n,而后者又被定义为等效于 的n重复评估++a

24.2.3p2 中的表 107 定义了表达式++r(其中r是输入迭代器),其前提条件是“可取消r引用”。

23.2.1p6 ...end() 返回一个迭代器,它是容器的结束值。如果容器为空,则 begin() == end()。

请注意,在您的示例中,v确实是空的。这简化了证明;否则,将需要更多的引用来证明operator++重复应用v.size()tov.begin()会产生v.end().

24.2.1p5 ...库从不假定过去的值是可取消引用的...

于 2013-07-18T18:46:03.020 回答