set 과 map 도 마찬가지로 iterator 와 const_iterator 가 있다.
하지만 다른 컨테이너들 (vector, list, deque, ..) 과 다른점은 set, map 은 데이타의 내용이 원소의 순서에 영향을 미친다는 것이다.
set, map 은 내부적으로 tree 로 구현되어 있다. 따라서 들어오는 원소에 따라서 트리의 구성이 달라지게 된다. 그렇기 때문에 set, map 의 iterator 에는 다음과 같은 문제가 있다.
std::set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
std::set<int>::iterator iter = s.begin();
*iter = 4;
assert(s.find(2) != s.end());
s.insert(1);
s.insert(2);
s.insert(3);
std::set<int>::iterator iter = s.begin();
*iter = 4;
assert(s.find(2) != s.end());
이 코드의 assert 구문은 보증할 수가 없다.
내부 구현에 따라 운이 좋게 이 케이스에 대해서는 assert 가 안 날 수도 있지만 분명히 잘 못된 코드이고 앞으로의 동작을 보증할 수 없게 된다. 내부적으로 구성해 놓은 트리의 값을 임의로 바꾸었기 때문이다.
(VC9 에서 테스트 해보면 assert 가 발생한다.)
그러므로 set, map 은 iterator 를 허용하면 안된다. const_iterator 만 허용해야 하는 것이다. 그래서 c++0x 부터는 set, map 의 iterator 는 const iterator 로만 동작을 하도록 표준이 바뀌었다.
다행이도 gcc 같은 경우는 꽤 오래전부터 (정확한 버전은 모름) iterator 를 const_iterator 와 같게 처리 해 왔다. 따라서 위와 같은 코드는 다음과 같은 에러를 내게 된다.
error: assignment of read-only location ‘iter.std::_Rb_tree_const_iterator<_Tp>::operator* [with _Tp = int]()’
Visual C++ 도 10 (Visual Studio 2010) 부터는 위의 코드를 허용하지 않도록 바뀌었다. 따라서 다음과 같은 에러를 낸다.
error C3892: 'iter' : you cannot assign to a variable that is const
VC10 은 c++0x 의 문법이 대거 적용되었으므로 위의 문제도 함께 해결된 것이다.
만약 최신 컴파일러를 쓰지 않는다면 주의해야 겠으며, 가장 좋은 방법은 set, map 은 const_iterator 만을 쓰는 것이다.



