簡體   English   中英

std :: map :: begin()之前的STL迭代器

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM