결론부터 말하면
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 |