2015-06-14 46 views
2

我認爲我們可以通過它的非const const迭代器爲容器的元素賦值一個新值。所以我試過:通過迭代器分配給一個元素

#include<iostream> 
#include<set> 

typedef std::set<int>::iterator it; 

std::set<int> set_int; 

int main() 
{ 
    set_int.insert(1); 
    it i = set_int.begin(); 
    *i = 11; //error: assignment of read-only location 
} 

並失敗。我爲什麼失敗?

回答

4

根據標準N4431§23.2.4/ 6關聯容器[associative.reqmts]重點礦山):

關聯容器的iterator是雙向迭代類。 對於值類型與鍵類型相同的關聯容器,iterator和const_iterator都是常量迭代器。它是 未指定iterator和const_iterator是否是相同的類型。 [注意:在這種情況下,iteratorconst_-iterator具有相同的語義,並且iterator可以轉換爲const_iterator。用戶可以通過在其功能參數列表中始終使用const_iterator來避免違反One Definition Rule。 - end note]。

std::set是一個關聯容器,其值類型與鍵類型相同,因此std::set<T>::iterator是一個常量迭代器。因此,你得到的失敗是很有道理的。

+0

不知道該規則也適用於地圖,multiset,multimap,謝謝。 –

3

A set實際上並沒有非const迭代器,因爲它的元素是不可變的。如果你考慮一下,假設你通過迭代器來改變密鑰。爲什麼窮人集合會移動節點以保持樹不變等等?

有關更詳細的&細微討論,請參閱由Angelika Langer提供的this piece

3

std::set在內部保持元素的順序。它基本上是一個紅黑樹二進制實現,並使用std :: less <>作爲其默認比較器。所以,如果我稍微修改您的示例如下:

typedef std::set<int>::iterator it; 
    std::set<int> set_int; 
    set_int.insert(1); 
    set_int.insert(6); //I added 
    it i = set_int.begin(); //error: assignment of read-only location 
    *i = 11; 

11着適合於您的std ::設置容器的第一個迭代器位置,因爲它違反了秩序。

因此很明顯,我們無法使用迭代器引用std::set來更新元素。編譯器不允許它,你會得到編譯器錯誤。