[英]Is the order of iterating through std::map known (and guaranteed by the standard)?
我的意思是 - 我們知道std::map
的元素是根據鍵排序的。 所以,假設鍵是整數。 如果我使用for
從std::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()
,它是由比較運算符確定的最大元素,以及兩個鍵值a
和b
,表達式為!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::set
, std::multiset
, std::map
和std::multimap
進行排序 std::multiset
和std::multimap
,標准不對等效元素強加任何順序保證(即那些比較相等的元素) 在C ++ 11中:
std::set
, std::multiset
, std::map
和std::multimap
進行排序 std::multiset
和std::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.