반복자는 컨테이너 안에 저장된 원소들을 차례대로 순환할 수 있는 객체이다.
입력 반복자 - 전방향 읽기 istream
출력 반복자 - 전방향 쓰기 ostream, inserter
전방향 반복자 - 전방향 읽기, 쓰기
양방향 반복자 - 전방향, 역방향 읽기, 쓰기 - list,set,multiset,map,multimap
랜덤 액세스 반복자 - 랜덤 액세스 - vector,deque,string,array
1. 입력 반복자 - 오로지 원소를 전진 방향으로만 읽기 액세스할 수 있는 반복자이다.
한번에 한개의 원소만을 읽어들일 수 있다는 사실이다.
2. 출력 반복자 - 오로지 원소를 전진 방향으로만 쓰기 액세스할 수 있는 반복자이다.
동일한 범위에 대해서 두 번 이상 반복자를 사용하여 순회할 수 없다.
첫번째 단어 이후에 나오는 두 번째 단어를 덮어쓰기보다는 차례대로 출력한다.
3. 전방향 반복자 - 입력반복자 + 출력반복자
ex) 출력반복자는 비교 동작을 지원하지 않기 때문에 시퀀스의 끝을 나타내는 반복자와 비교를 할 수 없다.
while(true){
*pos = foo();
++pos;
}
전방향반복자는 end()일 경우를 참조할 수 있기 때문
while(pos != coll.end()){
*pos = foo();
++pos;
}
4. 양방향 반복자 - 원소를 역순으로 순회할 수 있는 기능을 추가한 전방향 반복자
5. 랜덤 액세스 반복자 - +.-와 같은 반복자 연산자를 제공할 뿐만 아니라 오프셋을 더하거나 뺄 수도 있고,
<,>연산자를 사용하여 두 반복자를 비교할 수 도 있다.
랜덤 액세스를 제공하는 컨테이너(vector,deque), 스트링(string,wstring),
기본의 배열(array,pointer)
ex)
vector<int> coll;
for(int i=-3;i<=9;++i){
coll.push_back(i);
}
//총 몇개의 원소를 가지고 있는지 출력한다.
cout << "number/distance: " << coll.end() - coll().begin() << endl;
//모든 원소를 출력한다.
// 주의 : != 연산자 대신 < 연산자를 사용한다.
vector<int>::iterator pos;
for(pos=coll.begin();pos<coll.end();++pos){
cout << *pos << '';
}
cout << endl;
//모든 원소를 출력한다.
for(int i=0;i<coll.size();++i){
cout<<coll.begin()[i] << ' ';
}
cout << endl;
//모든 두번째 원소를 출력한다.
// += 연산자를 사용한다.
for(pos=coll.begin();pos<coll.end()-1;pos+=2){
cout << *pos << '';
}
cout << endl;
//list,set,map처럼 랜덤 액세스 반복자를 사용하지 않는 컨테이너에 대해서는 동작하지 않는다.
//루프의 종료 조건으로 제공된 < 연산자는 오직 랜덤 액세스 반복자만이 가능하다는 사실을 기억해두자.
//vector, deque, string, array
6. vector 반복자의 증,감소 문제
std::vector<int> coll;
if(coll.size() > 1) {
sort(++coll.begin(),coll.end()); // 컴파일 에러
}
//원인은 vector의 반복자의 구현을 일반적인 포인터처럼 구현하였기 때문이다.
7. 보조 반복자 함수
a) advance() 함수는 인자로 전달된 값만큼 반복자의 위치를 증가시킨다.
주의사항은 이동한 위치가 end()를 넘는지 검사하지 않는다.
ex) list<int> coll;
list<int>::iterator pos = coll.begin();
advance(pos,3); //pos의 위치를 3만큼 전진시킨다.
b) distance() 함수는 두 반복자의 위치 차이를 계산하기 위해서 제공된다.
주의사항은 같은 컨테이너의 반복자이어야 한다.
list<int>::iterator pos;
pos = find(coll.begin(),coll.end(),5);
if(pos != coll.end(){
cout << distance(coll.begin(),pos) <<endl;
}
c) iter_swap()함수는 두 반복자가 가리키고 있는 값을 교체하는 기능을 제공한다.
반복자가 같은 타입일 필요는 없다, 가리키는 값이 할당될 수 있어야 한다.
//첫번째, 두번째 값을 교환한다.
iter_swap(coll.begin(),++coll.begin());
8. 역방향 반복자
rbegin()은 역방향 반복자의 첫 번째 원소의 위치를 반환한다. 따라서 정상적인 순서로 본다면 마지막 원소의 위치를
반환한다.
rend()는 역방향 반복자의 마지막 원소의 위치를 반환한다. 따라서 정상적인 순서로 본다면 첫번째 원소의
앞 위치를 반환한다.
역방향 반복자 디자이너들은 한 가지의 트릭을 사용하였다. 역방향 반복자에 의해서 정의되는 새로운 범위를
정의한 것이다. 첫 번째 위치에서는 원소를 포함하지 않고 마지막 위치에서 원소를 포함한다.
base()를 사용하여 역방향 반복자를 일반 반복자로 전환하기
//반복자를 역방향 반복자로 변경한다.
list<int>::reverse_iterator rpos(pos);
list<int>::iterator rrpos;
//역방향 반복자를 반복자로 변경한다.
rrpos = rpos.base();
9. 삽입 반복자
a) 후위 삽입 반복자
- 컨테이너의 push_back()멤버함수는 호출하여 컨테이너의 끝부분에 값을 추가시킨다. vector,deque,list,string
back_inserter()
vector <int> coll;
1) back_insert_iterator<vector<int>> iter(coll);
*iter = 44;
2) back_inserter(coll) = 44;
b) 전위 삽입 반복자
- 컨테이너의 push_front()멤버함수를 호출하여 컨테이너의 앞부분에 값을 추가시킨다. deque,list
list<int> coll;
1) front_insert_iterator<list<int>> iter(coll);
*iter = 1;
2) front_inserter(coll) = 44;
c) 일반적인 삽입 반복자
set<int> coll;
1) insert_iterator<set<int>> iter(coll,coll.begin());
*iter = 1;
2) inserter(coll,coll.end()) = 45;
10. 스트림 반복자
1) 출력 스트림 반복자
ostream_iterator <int> intWriter(cout,"\n");
*intWriter = 42;
copy(coll.begin(),coll.end(), //구별자없이 모든 원소를 기록한다.
ostream_iterator<int>(cout));
copy(coll.begin(),coll.end(), //"<" 구별자를 사용하여 모든 원소를 기록한다.
ostream_iterator<int>(cout,"<"));
42
123456789
1<2<3<4<5<6<7<8<9
2) 입력 스트림 반복자
istream_iterator<int> intReader(cin); //cin으로부터 정수 타입을 읽어들이는 입력 스트림 반복자 생성
istream_iterator<int> intReaderEOF; //"끝 스트림 반복자" 생성
while(intReader != intReaderEOF){
cout <<"once: " <<*intReader <<endl;
++intReader;
}