咱們在C++中使用STL的容器時,常常會用到迭代器。使用迭代器能夠很方便的進行容器元素遍歷和修改等操做。編程
近日,在使用Visual Studio 2015編程的時候發現,set的迭代器直接就是const_iterator類型,而vector的迭代器則是普通的iterator類型,這是爲何呢?今天就和你們一塊兒來探究一下。數據結構
Set/Map類型spa
1 set<int>::iterator it1; 2 map<int,int>::iterator it2; 3 it1 = set1.begin(); 4 *it1 = 1;
在Visual Studio 2010版本以上,聲明一個集合或者一個哈希表的迭代器,雖然咱們寫的是普通的iterator,可是其實它們都是const_iterator,即一個沒法對元素進行修改操做的const引用(set取到的iterator則是const的,而map取到的iterator的key則是const的)。所以,若是使用該迭代器對容器中元素進行修改操做則會編譯不經過(如第三、4行代碼),對於map的迭代器同理。設計
爲何不容許對元素進行修改?code
我認爲這其中有兩個緣由:blog
① 由於set和map這種類型的容器,須要根據key來保持有序或者是確保元素的惟一性,因此不容許用戶直接對元素進行修改。若是容許用戶在使用iterator時直接對元素進行修改間接的修改了元素的鍵值,頗有可能致使非惟一性或無序。排序
② 正是因爲這種類型的容器須要保持元素的有序性,底層可能用了某種數據結構來保存(如:堆),若是頻繁的修改元素,則內部可能須要屢次進行排序,致使效率低下。it
怎麼對元素進行修改?io
既然普通的iterator沒法直接對元素進行修改,那麼咱們應該怎麼作呢?下面就給出兩種方法。編譯
① 使用容器的erase()和insert()方法。若是想修改某個元素,那麼直接刪掉它,再將修改過的元素插入到原有的容器中。這種方法的缺點是效率過低。
② 使用const_cast。
咱們都知道const_cast能夠去掉任何底層const修飾,使得一個const變量成爲非const的,這裏咱們就使用這一點來消除iterator的const。
1 for (set<int>::iterator i = IntSet.begin(); i != IntSet.end(); i++) 2 { 3 int &item1 = const_cast<int&>(*i); 4 //do something here 5 }
可是,我仍是不建議這麼作,雖然這樣能夠使用迭代器進行修改元素的操做,但這與自己設計出來的思想相違背。