![](/img/trans.png)
[英]Decrementing std::vector::iterator before std::vector::begin()
[英]Why "operator<" for std::vector<int>::iterator seems to compare absolute values when out of range (before .begin())?
std::vector 上的 cppreference似乎没有任何std::vector<T>::iterator
类型的链接。 由于它是连续 memory 上的双向迭代器,我认为它可以是“负数”。
std::distance(vec.begin(), std::prev(vec.begin())
产生-1
,我最终使用std::distance
来比较循环的迭代器。
但我期待while(iterLeft < iterRight)
是一个有效的检查,它比while(std::distance(iterLeft, iterRight) > 0)
短。
然而,这段代码表明operator<
出于某种原因似乎比较绝对值:
(这段代码幸存下来重现了问题。实际代码有一个可变大小的向量作为输入)
#include <vector>
#include <iostream>
int main()
{
std::vector<int> vec{};
auto iterLeft = vec.begin(),
iterRight = std::prev(vec.end());
std::cout << "Left = " << std::distance(vec.begin(), iterLeft)
<< ", Right = " << std::distance(vec.begin(), iterRight)
<< ", Left < Right: " << std::boolalpha << bool(iterLeft < iterRight)
<< std::endl;
return 0;
}
返回的程序:0
左 = 0,右 = -1,左 < 右:真
https://godbolt.org/z/PErY35Ynj
所以基本上 UB不是由std::prev(vec.end())
引起的,而是由超出范围的迭代器 goind 引起的(在.begin()
之前)。
代码示例只是为了重现问题。 最初的代码是用 2 个迭代器遍历一个数组,目的是使代码声明(意思是处理空的 arrays 而不进行显式检查)。
for (auto leftIter = vec.begin(), rightIter = std::prev(vec.end()); leftIter < rightIter;)
{
// do stuff
++leftIter;
--rightIter;
}
该代码在大多数情况下工作正常,但 arrays 为空。因此出现了这个问题。
如果将 std::distance 应用于同一范围内的有效迭代器,则std::distance
可以产生负值,并且operator<
可用于比较同一范围内有效迭代器的顺序。 它以预期的方式进行比较。 iterLeft < iterRight
将等效于std::distance(iterLeft, iterRight) > 0
。
然而,唯一有效的迭代器是从begin()
到end()
范围内的迭代器。 尝试在begin()
“之前”或“之后” end()
获取迭代器会导致未定义的行为。
所以std::distance(vec.begin(), std::prev(vec.begin())
不会导致-1
。它具有未定义的行为。
同样,在您的代码块中, std::prev(vec.end())
具有未定义的行为,因为向量为空,因此vec.begin() == vec.end()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.