[英]STL iterator before std::map::begin()
在C ++ 11的std::map
,是否有一些有效的迭代器x使得++ x保證等於map::begin()
? 我想檢測一下我剛剛調用的函數(我的)是否已經從函數前面走了一個迭代器。 該函數將迭代器向后移動一個位置。
答案是否適用於圖書館的其他部分?
不,在std
容器中開始之前的迭代器都是UB(反向迭代器除外,這可能無法解決您的問題)。
您可能需要修復有問題的功能。 如果失敗了,請在調用之前將其包裝並捕獲不良行為。 如果不這樣做,您可以在map
鍵類型排序中插入負無窮大元素,並添加一個sentinal值。 如果做不到這一點,你可以編寫迭代器適配器來封裝你的map
迭代器,它們可以在沒有UB的情況下開始。
這些是按我的推薦順序排列的。 每種方法都有失敗的方式,而且隨着我的推薦變得更加偏遠,它們會更容易出錯並且更加危險。
非常重要的是要意識到標准庫容器是半開放范圍[begin, end)
,即你可以迭代一次過去。 對於雙向(和隨機)迭代器,您也可以執行--end()
並從邊緣返回。 通過*end()
--begin()
引用一個*end()
是未定義的行為,因此通過--begin()
或begin() - 1
遞減開始迭代器。 這只有一個例外: std::forward_list
有一個before_begin()
引用的迭代器before_begin()
,它滿足++before_begin() == begin()
(但請注意,對於forward_list
你也不能減少begin()
)。
雙向迭代器的這種基本不對稱性意味着反向迭代器是常規迭代器周圍的薄包裝器。 在大多數標准庫實現中,它們只包含underyling迭代器的副本base_
。 增加std::reverse_iterator
調用類似--base_; return *this;
--base_; return *this;
,並取消引用它會auto old = base_; return *--old;
auto old = base_; return *--old;
。 在begin()
之前,底層迭代器決不會減少,並且不會以這種方式解除end()
解除引用。
下面是迭代支持雙向或隨機迭代器的容器的四種方法,以及各種迭代器之間的關系( .base()
將std::reverse_iterator
轉換回其底層迭代器)
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
int main()
{
auto c = std::map<int, std::string>{ {1, "hello"}, {2, "world"} };
{ // 1) forward iteratation
auto it = begin(c);
for (; it != end(c); ++it){}
std::cout << std::boolalpha << (it == c.rbegin().base()) << "\n";
}
{ // 2) meh, backward iteration
auto it = end(c);
for (; it != begin(c); --it){}
std::cout << std::boolalpha << (it == c.rend().base()) << "\n";
}
{ // 2') better: reverse iteration
auto it = c.rbegin();
for (; it != c.rend(); ++it){}
std::cout << std::boolalpha << (it.base() == begin(c)) << "\n";
}
{ // 1') backward reverse, better avoid this
auto it = c.rend();
for (; it != c.rbegin(); --it){}
std::cout << std::boolalpha << (it.base() == end(c)) << "\n";
}
}
如果你的數據結構應該支持雙向迭代但是沒有成員迭代器.rbegin()
或rend()
,你可以通過std::reverse_iterator(end())
和std::reverse_iterator(begin())
自己定義它們。 std::reverse_iterator(begin())
,分別(這也是標准庫通常實現它們的方式)。
通過“從前面走迭代器”我假設你正在遞減這樣的前向迭代器:
// don't do this:
for(it = mymap.end(); --it >= mymap.begin(); ) { ... }
相反,增加一個反向迭代器,如下所示:
// this is better:
for(it = mymap.rbegin(); it != mymap.rend(); ++it) { ... }
-Jesse
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.