위와 같은 오류를 해결해봅시다.
Expression: cannot increment value-initialized map/set iterator
이는 iterator에 문제가 생겨 증가를 할 수 없다는 것인데요..
erase()
를 알아봅시다!
STL에서 컨테이너를 이용할 때, 컨테이너 안 요소를 삭제합니다.
같은 기능을 하는 remove도 있지만, 쓰임방법과 쓰임새가 조금 다르지요.
일단 큰 차이는, remove(요소)인 반면, erase(요소의 반복자) 입니다.
다음은 오류가 나는 코드 입니다.
// set 안에 있는 모든 요소를 제거합니다.
set<int> c; // c 안에 1, 2, 3 등 요소가 있다고 가정합시다.
for (auto iter = c.begin(); iter != c.end(); ++iter){
c.erase(iter);
}
연관 컨테이너의 경우(Associate container)
: set, map, multiset, multimap의 경우.
컨테이너의 어떤 요소가 erase될 때, 이 요소를 가리키고 있는 모든 반복자들이 무효화됩니다.
c.erase(i)가 복귀하자마자 i는 바로 무효화됩니다.
따라서 루프에 있는 ++i는 무효화되어 에러가 납니다.
이를 해결하기 위해서는,
erase를 호출하기 전에 반복자 i가 c의 다음 요소를 가리키도록 세팅하면 됩니다.
// set 안에 있는 모든 요소를 제거합니다.
set<int> c; // c 안에 1, 2, 3 등 요소가 있다고 가정합시다.
for (auto iter = c.begin(); iter != c.end();){
c.erase(iter++);
}
시퀀스 컨테이너(Sequence container)
: vector, deque, list, forward_list, string 등의 경우.
연속 메모리 컨테이너의 경우는 말이 좀 다릅니다.
여기서는 erase를 호출하면, 지워진 요소를 가리키는 반복자 뿐만 아니라, 그 외 모든 반복자가 무효화 되어, i++, ++i 등이 효과가 없어지게 됩니다.
따라서, erase의 반환값을 이용합니다. 반환값은 삭제된 요소의 다음 요소를 가리키는 반복자입니다.
// set 안에 있는 모든 요소를 제거합니다.
vector<int> c; // c 안에 1, 2, 3 등 요소가 있다고 가정합시다.
for (auto iter = c.begin(); iter != c.end();){
iter = c.erase(iter);
++iter;
}
이 방법을 연관 컨테이너에 적용하면 발휘되지 않습니다.
연관 컨테이너의 erase는 반환값이 void이기 때문입니다.
<참고> 이펙티브 STL, Scott Meyers
'lang > C,C++' 카테고리의 다른 글
[Class] 2. Class - 구성요소, 깊은복사 vs 얕은복사 (1818) | 2019.10.09 |
---|---|
[Class] 1. Class - 객체지향 프로그래밍 OOP 4가지 특징 (1313) | 2019.10.09 |
C++ String (#include <string>) (0) | 2019.09.03 |
[STL] priority_queue (0) | 2019.07.21 |
연산자 오버로딩 (0) | 2019.07.14 |
댓글