为什么比较"end()"迭代器合法?

sha*_*oth 17 c++ pointers iterator stl

根据C++标准(3.7.3.2/4)使用(不仅是解除引用,还有复制,转换,其他任何),无效指针是未定义的行为(如果有疑问也会看到这个问题).现在,遍历STL容器的典型代码如下所示:

std::vector<int> toTraverse;
//populate the vector
for( std::vector<int>::iterator it = toTraverse.begin(); it != toTraverse.end(); ++it ) {
    //process( *it );
}
Run Code Online (Sandbox Code Playgroud)

std::vector::end()超出容器最后一个元素的假设元素的迭代器.那里没有元素,因此使用指针通过迭代器是未定义的行为.

那么!= end()工作怎么样呢?我的意思是为了进行比较,需要构造迭代器包装无效地址,然后必须在比较中使用该无效地址,这也是未定义的行为.这样的比较合法吗?为什么?

Nic*_*wis 25

唯一的要求end()++(--end()) == end().的end()可能仅仅是一种特殊状态的迭代器是.没有理由的end()迭代器有对应于任何类型的指针.

此外,即使它是一个指针,比较两个指针也不需要任何类型的解引用.考虑以下:

char[5] a = {'a', 'b', 'c', 'd', 'e'};
char* end = a+5;
for (char* it = a; it != a+5; ++it);
Run Code Online (Sandbox Code Playgroud)

该代码将正常工作,它反映了您的矢量代码.

  • @sharptooth:数组的一个结尾是**不是**无效的指针. (14认同)

Joe*_*oeG 10

你是对的,无法使用无效的指针,但你错了指向一个超过数组中最后一个元素的元素的指针是无效的指针 - 它是有效的.

C标准6.5.6.8节说它定义明确且有效:

...如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向一个超过数组对象的最后一个元素的...

但无法解除引用:

...如果结果指向一个超过数组对象的最后一个元素,则它不应该被用作被评估的一元*运算符的操作数...

  • 关于C++的最后一句话是不正确的.如果你知道在数组之后另一个元素类型的对象驻留(如在multidim数组中)你*可以*取消引用它. (3认同)
  • 它在C++中是有效的(不是UB),在C中是UB,是的.但只有在那个位置确实有一个物体.见`5.7/5`和`3.9.2/3`. (3认同)
  • 如上所述,因为C和C++不一样,所以投票不一致.这有点误导. (2认同)

Unc*_*ens 5

结束时不是无效值(常规数组或迭代器都没有).你不能取消引用它,但它可以用于比较.

std::vector<X>::iterator it;
Run Code Online (Sandbox Code Playgroud)

这是一个奇异的迭代器.您只能为其分配有效的迭代器.

std::vector<X>::iterator it = vec.end();
Run Code Online (Sandbox Code Playgroud)

这是一个完全有效的迭代器.您不能取消引用它,但您可以使用它进行比较并减少它(假设容器具有足够的大小).