이 곳에 쓰인 모든 글은 Bjarne Stroustrup 교수님의
'The C++ Programming Language' 에서 발췌하여 직접 정리하였습니다.
1. 미리 알아둡시다. ( 대체 왜 remove랑 erase가 둘 다 있는거야? )
기본적으로 표준 알고리즘 함수들 ( algorithm 헤더 내에 있는 )은 절대 요소를 삽입하거나 삭제하지 않습니다.
요소에 대한 삽입 삭제는 순전히 프로그래머가 관리하여야 합니다. 그래서 컨테이너에서 push, pop, insert, erase등의 삽입, 삭제 함수를 관리합니다. ( 진짜입니다. cppreference의 algorithm에서 erase를 검색해보세요...! )
(std::remove는 삭제하는 것이 아닌, 앞으로 모으기만 합니다!)
간단히 std::vector<int> 에서 요소를 삭제한다고 생각해봅시다.
erase 라는 함수는 여러분이 생각하는 것과 동일하게 중간 값에 대해서 move (copy)시키는 작업을 합니다.
즉, 지우기로 한 값의 +1 위치가 end (last)가 아니라면 move (copy) 연산을 실행한 후, 맨 마지막 반복자의 destroy (소멸자)를 호출합니다.
우리가 만약 지우려고 한 값이 띄엄 띄엄 놓아져 있다면?
2. std::remove와 erase의 관계
1 | 2 | 3 | 2 | 2 | 1 |
이러한 값을 가진 vector가 있다고 해봅시다. '2' 라는 값을 지우기 위해선 우린 최소 2번의 erase를 호출하여야 합니다.
(물론 정렬 시키고 1회에 정리시키는 방법이 있긴 할 것 같습니다만...)
모든 '2'들은 vector의 중간에 있는 값이기 때문에 move연산이 계속 이루어 져야 합니다.
이를 위해 std::remove라는 표준 라이브러리가 있습니다.
표준 알고리즘함수인 std::remove는 실제로 컨테이너를 '삽입' 하거나 '삭제' 하지 않습니다. 그저 해당하지 않는 값들을 앞으로 이동시킵니다. 이 후의 처리는 사용자가 하여야 합니다.
1 | 3 | 1 | 2 | 2 | 1 |
std::remove를 통하여 vector의 값이 이렇게 바뀌었습니다. erase 1번을 통하여 모든 '2'값을 지워낼 수 있습니다.
결국 실행되는 함수는
std::erase(std::remove(v.begin(), v.end(), 2), v.end());
가 될 것입니다.
이것만으로 모든 '2'를 erase 1번만을 통해 지워낼 수 있습니다.
즉
remove-erase idiom은
std::remove는 forward_iterator를 받는데, 지우는 방법을 모르기 때문에 move (copy)를 이용한 값을 앞으로 이동시키만 할 뿐이며
표준 컨테이너에서 erase의 2회 이상의 호출을 막기위해서 생성된 것이며
실제적으로 삭제를 위해선 erase 함수를 호출하여야 합니다.
'C++ > STL' 카테고리의 다른 글
STL) 나만의 Allocator( 할당자 ) 만들기 - 2 (0) | 2019.04.17 |
---|---|
STL) 나만의 Allocator( 할당자 ) 만들기 - 1 (0) | 2019.04.16 |
std::list::splice (0) | 2019.04.12 |
STL) 반복자 어댑터 ( Iterator Adaptor ) (0) | 2019.04.12 |
STL) 분할, 정렬, 힙에 대한 추가 연산들 (stable_*, is_*, is_*_until) (0) | 2019.02.20 |