简体   繁体   English

为什么 std::vector 的 "operator<"<int> ::iterator 似乎在超出范围时比较绝对值(before.begin())?</int>

[英]Why "operator<" for std::vector<int>::iterator seems to compare absolute values when out of range (before .begin())?

cppreference on std::vector doesn't seem to have any links for std::vector<T>::iterator type. std::vector 上的 cppreference似乎没有任何std::vector<T>::iterator类型的链接。 Since it is a bidirectional iterator on a contigious memory, I supposed that it can be "negative".由于它是连续 memory 上的双向迭代器,我认为它可以是“负数”。
std::distance(vec.begin(), std::prev(vec.begin()) yields -1 , and I ended up using std::distance to compare iterators for a loop. std::distance(vec.begin(), std::prev(vec.begin())产生-1 ,我最终使用std::distance来比较循环的迭代器。
But I was expecting while(iterLeft < iterRight) to be a valid check, and it is shorter than while(std::distance(iterLeft, iterRight) > 0) .但我期待while(iterLeft < iterRight)是一个有效的检查,它比while(std::distance(iterLeft, iterRight) > 0)短。

This code, however, demonstrates that operator< for some reason seems to compare absolute values:然而,这段代码表明operator<出于某种原因似乎比较绝对值:
(This code surved to recreate the problem. The actual code had a variable-sized vector as an input) (这段代码幸存下来重现了问题。实际代码有一个可变大小的向量作为输入)


#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;
}

Program returned: 0返回的程序:0
Left = 0, Right = -1, Left < Right: true左 = 0,右 = -1,左 < 右:真

https://godbolt.org/z/PErY35Ynj https://godbolt.org/z/PErY35Ynj


So basically the UB is caused Not by std::prev(vec.end()) , but by an iterator goind out of range (before .begin() ).所以基本上 UB不是std::prev(vec.end())引起的,而是由超出范围的迭代器 goind 引起的(在.begin()之前)。


The code example is just to recreate the problem.代码示例只是为了重现问题。 Initially the code is to traverse an array with 2 iterators and the intent was to make the code declarative (meaning to handle empty arrays without an explicit check).最初的代码是用 2 个迭代器遍历一个数组,目的是使代码声明(意思是处理空的 arrays 而不进行显式检查)。

for (auto leftIter = vec.begin(), rightIter = std::prev(vec.end()); leftIter < rightIter;)
{
 // do stuff
 ++leftIter;
 --rightIter;
}

The code worked fine for most cases, but empty arrays. Hence the question.该代码在大多数情况下工作正常,但 arrays 为空。因此出现了这个问题。

std::distance can yield negative values if applied to valid iterators to the same range and operator< can be used to compare the ordering of valid iterators into the same range.如果将 std::distance 应用于同一范围内的有效迭代器,则std::distance可以产生负值,并且operator<可用于比较同一范围内有效迭代器的顺序。 And it does this comparison in the expected way.它以预期的方式进行比较。 iterLeft < iterRight will be equivalent to std::distance(iterLeft, iterRight) > 0 . iterLeft < iterRight将等效于std::distance(iterLeft, iterRight) > 0

However the only valid iterators are those in the range from begin() to end() .然而,唯一有效的迭代器是从begin()end()范围内的迭代器。 Trying to obtain an iterator "before" begin() or "after" end() causes undefined behavior.尝试在begin() “之前”或“之后” end()获取迭代器会导致未定义的行为。

So std::distance(vec.begin(), std::prev(vec.begin()) does not result in -1 . It has undefined behavior.所以std::distance(vec.begin(), std::prev(vec.begin())不会导致-1 。它具有未定义的行为。

Similarly in your code block std::prev(vec.end()) has undefined behavior because the vector is empty and so vec.begin() == vec.end() .同样,在您的代码块中, std::prev(vec.end())具有未定义的行为,因为向量为空,因此vec.begin() == vec.end()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在std :: vector :: begin()之前减少std :: vector :: iterator - Decrementing std::vector::iterator before std::vector::begin() 为什么我在std :: vector中使用索引超出范围的operator []时没有异常? - Why I don't get an exception when using operator [] with index out of range in std::vector? 向量 <int> :: iterator设置为begin时在向量的末尾开始 - vector<int>::iterator starts at end of vector when set with begin Vector :: iterator在与begin比较时崩溃 - Vector::iterator crashes on compare with begin 为什么std :: copy会抛出错误向量迭代器+偏移超出范围而无法复制 - Why is std::copy throwing an error vector iterator + offset out of range and not able to copy += 运算符后 std::string::begin() 迭代器是否无效? - Is std::string::begin() iterator invalid after += operator? 在std :: vector中插入迭代器范围 - Inserting iterator range in std::vector std :: map :: begin()之前的STL迭代器 - STL iterator before std::map::begin() 反向迭代器错误:&#39;rcit!= std :: vector &lt;_Tp,_Alloc&gt; :: rend()中的&#39;operator!=&#39;与_Tp = int,_Alloc = std :: allocator&#39;不匹配 - reverse iterator error : no match for 'operator!=' in 'rcit != std::vector<_Tp, _Alloc>::rend() with _Tp = int, _Alloc = std::allocator' std :: vector超出范围 - std::vector out of range
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM