繁体   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())?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM