我們在C++中使用STL的容器時,經常會用到迭代器。使用迭代器可以很方便的進行容器元素遍歷和修改等操作。
近日,在使用Visual Studio 2015編程的時候發現,set的迭代器直接就是const_iterator類型,而vector的迭代器則是普通的iterator類型,這是為什么呢?今天就和大家一起來探究一下。
Set/Map類型
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的)。因此,如果使用該迭代器對容器中元素進行修改操作則會編譯不通過(如第3、4行代碼),對於map的迭代器同理。
為什么不允許對元素進行修改?
我認為這其中有兩個原因:
① 因為set和map這種類型的容器,需要根據key來保持有序或者是確保元素的唯一性,所以不允許用戶直接對元素進行修改。如果允許用戶在使用iterator時直接對元素進行修改間接的修改了元素的鍵值,很有可能導致非唯一性或無序。
② 正是由於這種類型的容器需要保持元素的有序性,底層可能用了某種數據結構來保存(如:堆),如果頻繁的修改元素,則內部可能需要多次進行排序,導致效率低下。
怎么對元素進行修改?
既然普通的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 }
但是,我還是不建議這么做,雖然這樣可以使用迭代器進行修改元素的操作,但這與本身設計出來的思想相違背。