[英]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.