#stl 반복자 어댑터(Iterator Adaptors) - inserter(), back_inserter(), front_inserter()
transform(), copy() 알고리즘과 같이 연산을 하거나 단순 복사를 하는 알고리즘을 사용할 때, 결과물을 쓰기 위한 반복자(iterator)를 함수 인자로 받는다. operator =
로 값을 쓰기 때문에 결과물을 특정 컨테이너 뒤에 삽입하려면 귀찮은 과정을 거쳐야 한다. 이럴 때 쓰라고 만들어 놓은 게 반복자 어댑터이다. 내부 구현을 보면 operator =
를 오버로딩해서 push_back()
, push_front()
, insert()
를 호출한다.
// 벡터 정의
int arr1[] = { 0, 1, 2, 3, 4 };
int arr2[] = { 5, 6, 7, 8, 9 };
typedef std::vector<int> IntegerVector;
IntegerVector v1(arr1, arr1 + sizeof(arr1) / sizeof(arr1[0]));
IntegerVector v2(arr2, arr2 + sizeof(arr2) / sizeof(arr2[0]));
// v1 벡터의 원소를 v2 벡터에 append한다.
v2.resize(v1.size() + v2.size());
std::copy(v1.begin(), v1.end(), v2.end() - v1.size());
// 콘솔 출력
std::copy(
v2.begin(),
v2.end(),
std::ostream_iterator<int>(std::cout, " "));
반복자 어댑터를 사용 안 하면 resize()
와 반복자 연산을 해야 한다.
v2.reserve(v1.size() + v2.size());
std::copy(v1.begin(), v1.end(), std::back_inserter(v2));
reserve()
는 원소가 많을 때 여러 번의 메모리 할당을 막으려고 호출한다. 확실히 반복자 어댑터가 간편하고 코드도 더 직관적이다. 이거 땜씨롱 반복자 어댑터를 쓰는 거지.
inserter(), back_inserter(), front_inserter()는 각각 insert_iterator
, back_insert_iterator
, front_insert_iterator
를 생성하는데, back_insert_iterator
의 구현을 살펴보면,
template<class _Container>
class back_insert_iterator : public _Outit
{ // wrap pushes to back of container as output iterator
public:
explicit back_insert_iterator(_Container& _Cont)
: container(&_Cont)
{ // construct with container
}
back_insert_iterator<_Container>& operator=(
typename _Container::const_reference _Val)
{ // push value into container
container->push_back(_Val);
return (*this);
}
protected:
_Container *container; // pointer to container
};
operator =
오버로딩해서 push_back을 호출한다. preincrement, postincrement, dereference 연산자는 반복자와 같은 동작을 한다.
참고
- Effective STL - 항목 30