remove 알고리즘의 경우 범위를 나타내는 한쌍의 반복자를 인자로 받는다. 여기서 문제가 생기는데 반복자만으로는 어떤 컨테이너 인지 알수 없을 뿐더러 해당 컨테이너를 접근할수도 없다.
그 결과 remove 알고리즘을 호출하더라 하더라도 컨테이너에 들어있는 요소의 개수가 삭제되지 않는 결과가 나타나게 된다. 이유는
romove는 어느것도 진짜로 없애지 않는다. 없앨수 없기 때문이다.
실제로 remove가 하는 일은 지워질 데이터와 남아있을 데이터를 재배열 하는 것이다.
위의 코드는 remove를 실제로 사용하는 코드이다. 위의 코드중 remove를 호출하기 전의 상태는
즉 위와 같은 형식의 코드가 구성된다.
remove와 유사한 알고리즘으로 remove_if 가 존재하며 비슷하게 동작하는 unique(인접한 중복갑제거)도 존재한다. 즉 remove_if와 unique등은 remove와 마찬가지로 실제로 데이타를 삭제하기 위해서는 erase를 같이 호출해 주어야 한다.
vector<int> v;
v.reserve(10);
for(int i=1; i<=10; ++i)
{
v.push_back(i);
}
v[3] = v[5] = v[9] = 99;
remove(v.begin(), v.end(), 99);
v.begin() v.end()같은 상태이다. remove를 호출한 이후는
↓ ↓
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
│1 │2 │3 │99│5 │99│7 │8 │9 │99│
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘
v.begin() v.end()위와 같은 상태를 갖게 된다. 즉 remove는 남아있을 값을 앞쪽으로 모아 놓고 논리적인 마지막 위치의 반복자를 리턴하게 되는 것이다. 이후 remove에서 리턴한 반복자와 원래 컨테이너의 end() 반복자 사이의 요소를 컨테이너의 erase를 호출하여 삭제해줘야 한다.
↓ ↓
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│1│2│3│5│7│8│9│?│?│?│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
↑
remove에서 리턴된 반복자위치
vector<int> v;
…
v.erase(remove(v.begin(), v.end(), 99), v.end());
remove와 유사한 알고리즘으로 remove_if 가 존재하며 비슷하게 동작하는 unique(인접한 중복갑제거)도 존재한다. 즉 remove_if와 unique등은 remove와 마찬가지로 실제로 데이타를 삭제하기 위해서는 erase를 같이 호출해 주어야 한다.
주의할점 1
list의 경우는 예외적으로 remove 와 unique 맴버함수가 존재하며 위의 설명과는 다르게 바로 데이타를 삭제한다.
list의 경우는 예외적으로 remove 와 unique 맴버함수가 존재하며 위의 설명과는 다르게 바로 데이타를 삭제한다.
주의할점 2
위의 remove, remove_if, unique등은 삭제 대상이 되는 데이타는 신경쓰지 않고 덮어써 버리는 구조를 취하게 되므로 포인터를 컨테이너에 넣는 경우 주의해야 한다.(EffectiveSTL33)
위의 remove, remove_if, unique등은 삭제 대상이 되는 데이타는 신경쓰지 않고 덮어써 버리는 구조를 취하게 되므로 포인터를 컨테이너에 넣는 경우 주의해야 한다.(EffectiveSTL33)