簡體   English   中英

迭代 std::map 的順序是否已知(並由標准保證)?

[英]Is the order of iterating through std::map known (and guaranteed by the standard)?

我的意思是 - 我們知道std::map的元素是根據鍵排序的。 所以,假設鍵是整數。 如果我使用forstd::map::begin()迭代到std::map::end() ,標准是否保證我將因此迭代帶有鍵的元素,按升序排序?


例子:

std::map<int, int> map_;
map_[1] = 2;
map_[2] = 3;
map_[3] = 4;
for( std::map<int, int>::iterator iter = map_.begin();
     iter != map_.end();
     ++iter )
{
    std::cout << iter->second;
}

這是保證打印234還是實現定義?


現實生活中的原因:我有一個帶有int鍵的std::map 在極少數情況下,我想使用大於具體int值的鍵遍歷所有元素。 是的,聽起來std::vector是更好的選擇,但請注意我的“非常罕見的情況”。


編輯:我知道, std::map的元素已排序..無需指出(對於此處的大多數答案)。 我什至在我的問題中寫了它。
我在遍歷容器時詢問了迭代器和順序。 感謝@Kerrek SB 的回答。

是的,這是有保證的。 此外, *begin()為您提供最小的*rbegin() ,它是由比較運算符確定的最大元素,以及兩個鍵值ab ,表達式為!compare(a,b) && !compare(b,a)是真的被認為是平等的。 默認比較函數是std::less<K>

排序不是幸運的獎勵功能,而是它是數據結構的一個基本方面,因為排序用於確定兩個鍵何時相同(通過上述規則)並執行有效查找(實質上是二進制)搜索,其元素數量具有對數復雜度)。

這是由C ++標准中的關聯容器要求保證的。 例如,參見C ++ 11中的23.2.4 / 10:

The fundamental property of iterators of associative containers is that they
iterate through the containers in the non-descending order of keys where
non-descending is defined by the comparison that was used to construct them.
For any two dereferenceable iterators i and j such that distance from i to j is
positive,
  value_comp(*j, *i) == false

和23.2.4 / 11

For associative containers with unique keys the stronger condition holds,
  value_comp(*i, *j) != false.

我認為數據結構存在混淆。

在大多數語言中, map只是一個AssociativeContainer:它將一個鍵映射到一個值。 在“較新”的語言中,這通常使用哈希映射來實現,因此不保證訂單。

但是,在C ++中,情況並非如此:

  • std::map是一個已排序的關聯容器
  • std::unordered_map是C ++ 11中引入的基於哈希表的關聯容器

所以,為了澄清訂購的保證。

在C ++ 03中:

  • 保證根據鍵(和提供的標准)對std::setstd::multisetstd::mapstd::multimap進行排序
  • std::multisetstd::multimap ,標准不對等效元素強加任何順序保證(即那些比較相等的元素)

在C ++ 11中:

  • 保證根據鍵(和提供的標准)對std::setstd::multisetstd::mapstd::multimap進行排序
  • std::multisetstd::multimap ,標准規定等效元素(比較相等的元素)按照它們的插入順序排序(首先插入)
  • std::unordered_*容器,顧名思義,未訂購。 最值得注意的是,當容器被修改時(插入/刪除時),元素的順序可能會改變。

當標准說元素以某種方式排序時,它意味着:

  • 迭代時,您會看到定義順序的元素
  • 當反向迭代時,您會看到相反順序的元素

我希望這可以解決任何困惑。

這是保證打印234還是它的實現定義?

是的, std::map是一個已排序的容器,由Key和提供的Comparator排序。 所以它是有保證的。

我想用密鑰迭代所有元素,大於具體的int值。

這肯定是可能的。

是的...... std::map的元素具有嚴格的弱排序,這意味着元素將由一個集合組成(即,不會重復“等於”的鍵),並確定相等性通過測試任意兩個密鑰A和B,如果密鑰A不小於密鑰B,並且B不小於A,則密鑰A等於密鑰B.

話雖如此,如果該類型的弱排序不明確(在您的情況下,您使用整數作為鍵類型,這不是問題),您無法正確排序std::map的元素。 您必須能夠定義一個操作,該操作定義您在std::map中使用的類型的總順序,否則您將只有元素的部分順序,或者poset,它具有A可能的屬性在這種情況下通常會發生的事情是,您將能夠插入鍵/值對,但如果您遍歷整個地圖,則可能最終會出現重復的鍵/值對,和/或當您嘗試在std::map::find()執行特定鍵/值對的std::map::find() ,檢測“缺少”鍵/值對。

為了完整起見,我想提一下,如果您的容器包含指針,則由於ASLR 的原因,每個新程序運行的迭代順序可能會有所不同。 因此,即使一次運行的順序確定性的,但多次運行中的順序不是

這對於正確性是否重要取決於特定程序。

begin()可以給出最小的元素。 但這是實施所依賴的。 它是在C ++標准中指定的嗎? 如果沒有,那么做出這個假設是危險的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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