1 minute read

vector에서 홀수인 값을 지워야 한다면?

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    vector<int> v;
    v.push_back(1);
	v.push_back(4);
	v.push_back(3);
	v.push_back(5);
	v.push_back(8);
	v.push_back(2);
    // 1 4 3 5 8 2
}

위와 같은 벡터가 있을 때, 홀수의 값을 찾아지우는 방법은 여러가지가 있지만 쉽게 생각할 수 있는 방법은 벡터의 erase 함수를 이용해서 반복문을 돌면서 지우는 방법이 있다.

이것 외에도 alorithm라이브러리에 정의되어 있는 remove 함수를 사용할 수도 있다. 함수의 사용법을 쓱 보고 보통 아래와 같은 방법을 사용해볼 수 있을 것이다.

// 함수 객체 활용
struct IsOdd
		{
			bool operator() (int n)
			{
				return (n % 2) != 0;
			}
		};

// remove_if는 iterator를 반환함
vector<int>::iterator it = remove_if(v.begin(), v.end(), IsOdd());

1 4 3 5 8 2의 원소를 가지고 있는 벡터에서 홀수의 값을 제거하고 나면 4 8 2가 벡터에 남아있을 것으로 마땅히 기대할 것이다. 그런데 디버깅 모드로 벡터의 값을 확인해보면 4 8 2 5 8 2라는 묘한 값을 가지고 있다. 무슨 일이 일어난걸까?

remove_if의 구현부

cppreference.com에서 remove_if를 확인해보면 아래와 같다.

template<class ForwardIt, class UnaryPredicate>
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p)
{
    first = std::find_if(first, last, p);
    if (first != last)
        for(ForwardIt i = first; ++i != last; )
            if (!p(*i))
                *first++ = std::move(*i);
    return first;
}

단순히 벡터의 원소를 지우는 것이 아니라 move를 이용해서 짝수인 값을 앞으로 땡겨온다는 것을 확인할 수 있다. 결과적으로 짝수를 앞으로 다 떙겨오고난 이후의 위치를 가리키는 iterator를 반환한다.

그러니까 벡터의 원소를 삭제해주는 작업을 추가해주지 않으면 원하는 결과를 얻지 못하고, 프로젝트에 잘못된 영향을 끼칠 가능성이 생긴다.

그래서 우리가 기대하는 4 8 2의 값을 얻기 위해서는 아래의 코드를 추가해줘야한다.

v.erase(it, v.end());  // 짝수값 이후를 나타내는 위치부터 vector의 끝까지 지워버리기

Tags:

Categories:

Updated: