본문으로 바로가기

remove-erase 고찰

category C++/STL 2021. 5. 3. 03:43

이 곳에 쓰인 모든 글은 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::removeforward_iterator를 받는데, 지우는 방법을 모르기 때문에 move (copy)를 이용한 값을 앞으로 이동시키만 할 뿐이며

표준 컨테이너에서 erase의 2회 이상의 호출을 막기위해서 생성된 것이며

실제적으로 삭제를 위해선 erase 함수를 호출하여야 합니다.