2013-08-25 40 views
2

std::unordered_map<K,T>提供像find這樣的方法,返回std::unordered_map<K,T>::iterator。據我所知,一個迭代器保持有效,除非重新哈哈發生。C++:從值類型指針轉換爲包含迭代器

但我懷疑的是,沒有用於雙向傳遞::iterator沒有保證的方式 - >T * - >::iterator,類似於「黑客」,也就是在Linux做鏈表。我認爲這是因爲迭代器只需要通過->second可解引用,但我沒有看到在容器內部需要持久存儲類型。

那麼,我說得對嗎?我是否需要保留迭代器,或者以後是T *ptr = &myiterator->second可重新映射到其成員地址爲ptr的迭代器指針?

這個問題自然也適用於其他容器的迭代器。

+2

您必須存儲迭代器。 –

+0

並非每個迭代器都會產生T * – 4pie0

+0

@computer:您的意思是,'&myiterator-> second'不需要產生存儲在容器中的實際值的地址? –

回答

2

第一個問題很簡單:一般來說,沒有直接的方法可以從一個指向元素的指針或從一個值獲取迭代器。也就是說,要從一個值中獲取迭代器,通常需要搜索容器。由於std::vector<T>必須是連續的,你可以使用一個簡單的計算(這需要v非空)得到一個指針迭代器:

std::vector<T> v(...); 
T* ptr = ...; 
std::vector<T>::iterator it(v.begin() + (ptr - &v[0])); 

要跟蹤迭代器和值是否保持穩定,不完全瑣碎作爲相關的保證被分佈在多個子句,例如:

  1. 23.2.1 [container.requirements.general]段落11:

    除非另有規定(明確地或通過用其他函數定義函數),調用容器成員函數或將容器作爲參數傳遞給庫函數不應使迭代器無效或更改其中的對象的值容器。

  2. 23.2.4 [associative.reqmts]段9:

    插入和佈設成員不得影響迭代器和引用到容器的有效性,並擦除成員應僅無效迭代器並提及被擦除的元素。

  3. 23.2.5 [unord。req]第9段:

    ...重新散列無效迭代器,更改元素之間的排序順序,並更改哪些存儲元素出現,但不會使元素的指針或引用無效。 ...

  4. 23.2.5 [unord.req]第14段:

    插入和佈設成員不得影響到容器元素的引用的有效性,但可能會使所有迭代器的容器。 ...

  5. 23.2.5 [unord.req]段落15:

    插入件和佈設如果成員不應影響迭代器的有效性(N + N)< Z * B,其中N是插入操作前容器中元素的數量,n是插入元素的數量,B是容器的桶數,z是容器的最大負載因子。

上述條款應該是重要的條款相對於迭代器關聯容器的有效性。無序關聯容器中的迭代器有效性完全取決於容器是否被重新整理。似乎重新控制可以控制,以避免它發生意外。

但是,無序容器的整個想法是,使用find()來定位對象是非常有效的。應該永遠不需要將迭代器存儲到元素,因爲您可以找回它們。當然,如果您有std::unordered_multimap<K, V>std::unordered_multiset<V>,您可能需要知道您正在查看哪些等效元素。

1

關聯容器(setmulti_setmapmulti_map,他們​​弟兄)做無效指針或當您添加的元素到容器的引用;他們可以使迭代器失效。另外,當你移除元素時,只有迭代器,指針和對這些元素的引用纔會失效。這樣做的一個後果是,如果您獲取元素的地址,則只要該元素保留在容器中,該地址就保持有效。

沒有可移植的方式將元素的地址直接轉換爲指向該元素的迭代器。如果你需要這樣做,你必須搜索元素。

+0

我還沒有找到相應的標準部分,但是http://www.cplusplus.com/reference/unordered_map/unordered_map/rehash/說該迭代器在rehash上無效,而元素引用和指針(我OP中的「ValueT」)仍然有效。 –

+0

@JoSo - 你是對的。我糾正了我的答案。 –