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 연산자는 반복자와 같은 동작을 한다.




back_inserter 

Visual Studio 2005

Creates an iterator that can insert elements at the back of a specified container.

template<class Container>
   back_insert_iterator<Container> back_inserter(
      Container& _Cont
      );

Parameters

_Cont

The container into which the back insertion is to be executed.

back_insert_iterator associated with the container object _Cont.Remarks

Within the Standard Template Library, the argument must refer to one of the three sequence containers that have the member function push_backdeque Classlist Class, or vector Class.

// iterator_back_inserter.cpp
// compile with: /EHsc
#include <iterator>
#include <vector>
#include <iostream>

int main( )
{
   using namespace std;
   int i;

   vector<int> vec;
   for ( i = 0 ; i < 3 ; ++i )  
   {
      vec.push_back ( i );
   }
   
   vector <int>::iterator vIter;
   cout << "The initial vector vec is: ( ";
   for ( vIter = vec.begin ( ) ; vIter != vec.end ( ); vIter++)
      cout << *vIter << " ";
   cout << ")." << endl;

   // Insertions can be done with template function
   back_insert_iterator<vector<int> > backiter ( vec );
   *backiter = 30;
   backiter++;
   *backiter = 40;

   // Alternatively, insertions can be done with the
   // back_insert_iterator member function
   back_inserter ( vec ) = 500;
   back_inserter ( vec ) = 600;

   cout << "After the insertions, the vector vec is: ( ";
   for ( vIter = vec.begin ( ) ; vIter != vec.end ( ); vIter++ )
      cout << *vIter << " ";
   cout << ")." << endl;
}

Output

The initial vector vec is: ( 0 1 2 ).
After the insertions, the vector vec is: ( 0 1 2 30 40 500 600 ).

Header: <iterator>

반응형

+ Recent posts