std::remove, std::sort, std::replace
개요
C++ 표준 라이브러리에서 제공하는 std::remove
, std::sort
, std::replace
계열 함수들은 컨테이너의 원소를 정렬하거나, 특정 조건에 맞는 원소를 바꾸거나, 제거하는 데 사용되는 강력한 도구입니다. 이 함수들을 사용하면 복잡한 반복문 없이도 간결하고 효율적인 코드를 작성할 수 있습니다.
C++ 버전별 주요 키워드 도입 시기
- C++98:
std::sort
,std::replace
,std::replace_if
,std::remove
,std::remove_if
- C++20:
std::erase
,std::erase_if
(컨테이너용 비멤버 함수)
내용 설명
std::sort
: 지정된 범위의 원소들을 오름차순 또는 사용자가 정의한 비교 함수에 따라 정렬합니다.std::replace
,std::replace_if
: 범위 내에서 특정 값이나 조건을 만족하는 원소들을 새로운 값으로 교체합니다.std::remove
,std::remove_if
: 범위 내에서 특정 값이나 조건을 만족하는 원소들을 뒤로 보내고, 제거되지 않은 원소들의 새로운 끝을 가리키는 반복자를 반환합니다. 이 함수들은 컨테이너의 크기를 직접 변경하지 않으므로, 보통 컨테이너의erase
멤버 함수와 함께 사용됩니다 (Erase-Remove Idiom).std::erase
,std::erase_if
(C++20): C++20부터 도입된 비멤버 함수로, 컨테이너에서 특정 값이나 조건을 만족하는 원소를 직접 제거하여 Erase-Remove Idiom을 더 간결하게 사용할 수 있게 해줍니다.
예제 코드
#include <algorithm>
#include <chrono>
#include <cstdint>
#include <iostream>
#include <random>
#include <vector>
namespace
{
constexpr auto NUM_ELEMENTS = size_t{10U};
}; // namespace
std::int32_t gen()
{
static auto seed = std::random_device{};
static auto g = std::mt19937{seed()};
static auto d = std::uniform_int_distribution<std::int32_t>{-10, 10};
return d(g);
}
template <typename T>
void print_vector(const std::vector<T> &vec)
{
for (const auto v : vec)
{
std::cout << v << ' ';
}
std::cout << '\n';
}
int main()
{
auto my_vector = std::vector<std::int32_t>(NUM_ELEMENTS, 0U);
std::generate(my_vector.begin(), my_vector.end(), gen);
std::cout << "Initial: ";
print_vector(my_vector);
std::replace(my_vector.begin(), my_vector.end(), 0, 1000);
std::cout << "After replace 0 with 1000: ";
print_vector(my_vector);
std::replace_if(
my_vector.begin(),
my_vector.end(),
[](const auto val) { return val % 2 == 0; },
-1);
std::cout << "After replace even numbers with -1: ";
print_vector(my_vector);
std::sort(my_vector.begin(),
my_vector.end(),
[](const auto i, const auto j) { return i < j; });
std::cout << "Sorted (ascending): ";
print_vector(my_vector);
std::sort(my_vector.begin(),
my_vector.end(),
[](const auto i, const auto j) { return i > j; });
std::cout << "Sorted (descending): ";
print_vector(my_vector);
// Pre C++20 (Erase-Remove Idiom)
auto remove_it = std::remove(my_vector.begin(), my_vector.end(), -1);
my_vector.erase(remove_it, my_vector.end());
std::cout << "After remove -1 (C++98): ";
print_vector(my_vector);
// Post C++20
std::erase(my_vector, 7);
std::cout << "After erase 7 (C++20): ";
print_vector(my_vector);
std::erase_if(my_vector, [](const auto i) { return i < 0; });
std::cout << "After erase_if negative (C++20): ";
print_vector(my_vector);
return 0;
}
실행 결과
Initial: 8 -5 5 -1 5 10 -2 5 -10 3
After replace 0 with 1000: 8 -5 5 -1 5 10 -2 5 -10 3
After replace even numbers with -1: -1 -5 5 -1 5 -1 -1 5 -1 3
Sorted (ascending): -5 -1 -1 -1 -1 3 5 5 5
Sorted (descending): 5 5 5 3 -1 -1 -1 -1 -5
After remove -1 (C++98): 5 5 5 3 -5
After erase 7 (C++20): 5 5 5 3 -5
After erase_if negative (C++20): 5 5 5 3
실행 결과는 난수 생성에 따라 달라질 수 있습니다.
활용팁
- Erase-Remove Idiom 이해:
std::remove
는 원소를 실제로 삭제하지 않고 뒤로 미룰 뿐이라는 점을 기억해야 합니다. C++20 이전 버전에서는container.erase(std::remove(begin, end, value), end)
형태의 코드가 필수적이었습니다. - C++20 활용: C++20 이상을 사용한다면
std::erase
와std::erase_if
를 사용하여 코드를 더 간결하고 안전하게 작성할 수 있습니다. - 성능:
std::sort
는 평균적으로 O(N log N)의 복잡도를 가집니다.std::remove
,std::replace
계열 함수들은 O(N)의 복잡도를 가지므로, 대량의 데이터 처리 시에도 효율적입니다.
'개발 > C++ (98,03,11,14,17,20,23)' 카테고리의 다른 글
Modern C++ : std::transform & std::accumulate (98) (0) | 2025.09.10 |
---|---|
Modern C++ : std::generate, local static variables (98, 11, 14) (0) | 2025.09.09 |
Modern C++ : Lambda Expressions (11, 14, 17, 20) (1) | 2025.09.08 |
Modern C++ : std::numeric_limits (98, 11, 17) (0) | 2025.09.07 |
Modern C++ : std::chrono 날짜 및 시간대 (11, 14, 17, 20) (1) | 2025.09.06 |
Modern C++ : std::chrono 시간 측정 (11, 14, 17, 20) (0) | 2025.09.05 |
Modern C++ : std::mt19937 (11, 14, 17, 20) (0) | 2025.09.04 |
Modern C++ : std::filesystem (0) | 2025.09.03 |