咱们在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 }
可是,我仍是不建议这么作,虽然这样能够使用迭代器进行修改元素的操做,但这与自己设计出来的思想相违背。