본문 바로가기
lang/C,C++

[STL] erase

by Wordbe 2019. 9. 19.
728x90

위와 같은 오류를 해결해봅시다.

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

728x90

댓글