C++/STL

[C++] remove(remove_if) vs erase(erase_if)

sseram 2023. 7. 11. 22:06
반응형

결론부터 말하면

 

 

C++에서 둘은 완전히 다르다. 조심히 사용하여야 한다.

 

 

만약 'vector에서 특정한 조건을 만족시키는 값들을 삭제' 할 때 사용하려고 한다면 물론 둘 다 사용 가능하긴 하다.

다만 erase_if를 사용한다면 원하는 바를 바로 얻을 순 있지만,

remove_if를 사용한다면 추가적인 단계를 한 번 더 밟아야 할 것이다.

 


 

remove_if :

알고리즘은 컨테이너에서 조건을 만족하는 요소를 뒤로 이동시키고, 그 뒤에 유효한 요소 범위를 반환합니다.
실제로 요소를 삭제하지 않고 이동시킨 뒤, 이후의 유효한 요소만 남도록 컨테이너의 크기를 조정합니다.

 

라고 나와있다.

 

즉, "aa", "bb", "cc", "dd" 라는 vector가 있을 때, "bb"를 remove_if 한다고 하면

"aa", "cc", "dd", "bb" 라는 순서로 변경된 후, 해당 조건에 맞는 element가 시작 된 iterator를 돌려줄 뿐이다.

 

/// 제대로 돌지 않음.
#include <iostream>
#include <vector>

using namespace std;

int main() {
	vector<string> vecStr = { "aa", "bb", "cc", "dd" };

	remove_if(vecStr.begin(), vecStr.end(), [](const string& str) -> bool { return str == "bb"; });

	for (auto&& str : vecStr) {
		cout << str << endl;
	}

	return 0;
}

 

이런 식으로 코드를 작성한 후 빌드를 돌리면

 

 

warning C4858: 반환 값을 삭제는 중: The 'remove' and 'remove_if' algorithms return the iterator past the last element that should be kept. You need to call container.erase(result, container.end()) afterwards. In C++20, 'std::erase' and 'std::erase_if' are simpler replacements for these two steps.

 

위와 같이 빌드 경고가 뜬다.

즉, 내가 원하는 '컨테이너에서의 element 삭제'를 원한다면, 한 단계를 더 해야 한다.

 

/// 맞는 코드!
#include <iostream>
#include <vector>

using namespace std;

int main() {
	vector<string> vecStr = { "aa", "bb", "cc", "dd" };

	auto it = remove_if(vecStr.begin(), vecStr.end(), [](const string& str) -> bool { return str == "bb"; });

	vecStr.erase(it, vecStr.end());

	for (auto&& str : vecStr) {
		cout << str << endl;
	}

	return 0;
}

 

 

이런 식으로, 해당 iterator부터 그 컨테이너의 마지막 부분까지 erase를 추가로 해 주어야 한다.

 

 


erase_if :

erase_if 함수는 조건을 만족하는 요소를 컨테이너에서 삭제하고, 남은 요소들을 재정렬하여 유효한 요소 범위를 반환합니다.
erase_if 함수를 사용하면 조건을 만족하는 요소를 효율적으로 제거할 수 있습니다.

 

라고 나와있다.

즉, 위의 두 개의 동작을

 

#include <iostream>
#include <vector>

using namespace std;

int main() {
	vector<string> vecStr = { "aa", "bb", "cc", "dd" };

	erase_if(vecStr, [](const string& str) -> bool { return str == "bb"; });

	for (auto&& str : vecStr) {
		cout << str << endl;
	}

	return 0;
}

 

 

 

이렇게 간단하게 해결이 가능해진다.

다만, erase_if 는 C++20 부터 사용 가능하니 조심하도록 하자.

 

 

그러니까, 내가 C++17 이하의 버전을 쓴다면... 귀찮지만 어쩔 수 없이 remove_if를 요리조리 사용해야 하는 수 밖에..

반응형

'C++ > STL' 카테고리의 다른 글

[C++ 11] std::initializer_list  (2) 2023.11.19
[C++17] std::variant  (1) 2023.11.12
[C++20] Span  (1) 2023.07.04
[C++] Priority_queue  (0) 2023.06.04
[C++17] Optional  (0) 2023.05.28