簡體   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