[STL] 반복자 iterator
Updated:
Iterator는 컨테이너의 메모리 주소를 가리키기 위한 포인터와 같은 객체입니다. Iterator를 통해 컨테이너 안의 특정 지점의 내용을 접근 할수 있다는 점에서 포인터와 비슷하다고 볼 수 있습니다.
하지만 모든 iterator가 포인터와 같은 기능을 갖진 않으며 iterator는 기능에 따라 총 5가지로 분류됩니다.
Iterator의 다양한 타입들
1. 입력 반복자 $($Input Iterators) : one-pass algoritm (입력을 정확히 한번 순서대로 읽는 스트리밍 알고리즘) 에서만 사용될수 있다. 즉 컨테이너를 순차적으로 수행하고 원소들을 한번씩만 접근하는 반복자.
2. 출력 반복자 $($Output Iterators) : one-pass algorithm에서만 사용가능, 원소들을 한번씩만 쓸수 있는 반복자.
3. 순방향 반복자 $($Foward Iterators) : 읽기, 쓰기 모두 가능하고 순방향 이동 ++ 이 가능한 재할당 될 수 있는 반복자.
4. 양방향 반복자 $($Bidirectional iterator) : 일기, 쓰기 모두 가능하고 순/역방향 이동 ++/– 이 모두 가능한 반복자.
5. 임의 접근 반복자 $($Random access iterator) : 컨테이너 안의 모든 원소들에 랜덤하게 접근 가능하며 일기, 쓰기 가능하고 포인터와 같은 기능을 한다. +, -, += , -=, [] 연산이 가능한 반복자.
Iterator 사용의 장점
1. 프로그래밍 하기 편리하다. 컨테이너 안의 원소들을 순서대로 접근할때 배열의 경우 컨테이너 안의 원소수를 고려해 줘야 하지만 iterator의 경우 end() 멤버 함수를 통해 컨테이너의 사이즈를 고려해 주지 않아도 됩니다. ex)
#include<iostream>
#include<vector>
using namespace std;
int main(void)
{
vector<int> v = {1,2,3} //vector 선언
vector<int>::iterator it; //iterator 선언
cout<<"Without iterator = ";
//Iterator 사용 없이 원소 접근
for(int i=0; i<3; i++) cout<<v[i]<<' ';
cout<<"\nWith iterator = ";
//Iterator를 사용하여 원소 접근
for(int i=v.begin(); i!=v.end(); i++) cout<<*i<<' ';
return 0;
}
결과
Without iterators = 1 2 3
With iterators = 1 2 3
2. 코드 재사용이 가능하다. 위의 코드의 v를 vector가 아닌 list로 생성했다면 []의 경우 위의 코드를 그대로 사용할 수 없지만 iterator의 경우 어떠한 컨테이너의 원소들도 접근가능하므로 vector를 list로 바꿔주는거 하나로 위 코드의 재사용이 가능합니다.
3. 컨테이너의 동적 처리가 가능하다. Iterator는 원소들의 삽입 삭제가 간편하게 이루어 질 수 있도록 해줍니다.
#include<iostream>
#include<vector>
using namespace std;
int main(void)
{
vector<int> v = {1,2,3} //vector 선언
vector<int>::iterator it; //iterator 선언
for (int i = v.begin(); i != v.end(); ++i)
{
if (i == v.begin())
{
i = v.insert(i, 5);
// v의 시작지점에 5를 삽입
}
}
// v - 5 1 2 3
for (int i = v.begin(); i != v.end(); ++i)
{
if (i == v.begin() + 1) {
i = v.erase(i);
// i는 삭제된 원소의 다음 위치를 가리키고 있다.
}
}
// v - 5 2 3
for (i = v.begin(); i != v.end(); ++i)
cout << *i << " ";
return 0;
}
결과
5 2 3
Iterator 연산자 종류
- begin$($) : 컨테이너의 시작 지점을 반환.
- end$($) : 컨테이너의 맨 마지막 원소의
다음
위치를 반환 - advance$($iterator, offset) : 현재 위치의 iterator를 offset 만큼 뒤로 이동시킨다.
#include<iostream>
#include<iterator>
#include<vector>
using namespace std;
int main(void)
{
vector<int> v = {1,2,3};
//iterator가 시작 원소를 가리킴
vector<int>::iterator it = v.begin();
advance(it, 2); //iterator를 두칸 이동
cout<<*it;
return 0;
}
결과
3
- next$($iterator, offset) : iterator를 현재 위치에서 offset만큼 앞으로 이동시킨 새로운 iterator를 반환
- prev$($iterator, offset) : iterator를 현재 위치에서 offset 만큼 뒤로 이동시킨 새로운 iterator를 반환
#include<iostream>
#include<iterator>
#include<vector>
using namespace std;
int main(void)
{
vector<int> ar = { 1, 2, 3, 4, 5 };
//iterators를 vector에 선언
vector<int>::iterator ptr = ar.begin();
vector<int>::iterator ftr = ar.end();
// vector의 시작위치에서 3만큼 이동
auto it = next(ptr, 3);
// vector의 끝에서 한칸 더 뒤의 위치에서 3만큼 뒤로 이동
auto it1 = prev(ftr, 3);
cout << "The position of new iterator using next() is : ";
cout << *it << " ";
cout << endl;
cout << "The position of new iterator using prev() is : ";
cout << *it1 << " ";
cout << endl;
return 0;
}
결과
The position of new iterator using next() is : 4
The position of new iterator using prev() is : 3
- inserter$($container, position) : 컨테이너의 원하는 위치에 원소를 삽입
#include<iostream>
#include<iterator>
#include<vector>
using namespace std;
int main(void)
{
vector<int> ar = { 1, 2, 3, 4, 5 };
vector<int> ar1 = {10, 20, 30};
vector<int>::iterator ptr = ar.begin();
advance(ptr, 3); //ar의 시작점의 가리키던 iterator를 3만큼 이동
//ar의 3번째 원소 이후에 ar1의 시작부터 끝부분 까지를 삽입
copy(ar1.begin(), ar1.end(), inserter(ar,ptr));
cout << "new vector after inserting elements : ";
for (int &x : ar)
cout << x << " ";
return 0;
}
결과
new vector after inserting elements : 1 2 3 10 20 30 4 5
Leave a comment