[C++ 표준] STL 반복자(+ 반복자의 종류 Iterator Category

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!


Cpp Reference

위키 백과 표준 템플릿 라이브러리

반복자

  • 컨테이너에 저장되있는 원소들을 공통적인 방법으로 하나씩 접근할 수 있게 해줌.
    • 모든 컨테이너들이 다 같은 방법으로 반복자 사용 가능.
  • 각 타입에 ::iterator 또는 ::const_iterator 를 뒤에 붙여주면 사용이 가능하다.
    • vector 컨테이너의 반복자 itr
      • vector<int>::iterator itr;
    • vector 컨테이너의 const한 반복자 citr
      • vector<int>::const_iterator citr;
  • 포인터와 비슷하게 사용한다.
    • 간접 참조 가능
      • itr = v.begin() + 2 에서 *itr 간접 참조를 하면 세번째 원소 값이 리턴된다.
  • iterator 와 const_iterator 의 차이
    • const_iterator 는 반복자가 가리키는 원소의 값을 변경하지 못한다.
      • 반복자 값이 변경되지 못하는게 아니고 반복자가 가리키는 원소의 값이 변경될 수 없는 것!
    • 일반 반복자는 포인터와 비슷하고 const 반복자는 const 포인터와 비슷하다. (간접참조로 값을 변경하지 못하는)
  • 초기화 하는 방법
    • itr = container.begin()
      • 컨테이너이름.begin() 하면 첫번째 원소의 iterator를 리턴


반복자의 종류

unordered_map<string, set<int>> db;

set 컨테이너는 자동으로 정렬이 된다는 것에 착안하여 처음에는 이렇게 Value를 vector가 아닌 set으로 했었다.

set<int>::iterator itr = lower_bound(score.begin(), score.end(), stoi(condition[4]));
answer.push_back(score.end() - itr); // ❌❌ 에러 발생! 

근데 set의 반복자끼리를 사칙연산 하려고 하니 자꾸 불가능하다고 에러가 뜨는 것이였다. vector 반복자는 잘만 되던데 뭐지 싶었다. (근데 set이 만약에 반복자 연산에 문제 없었다 하더라도 info for문 안에서 매번 자동 정렬이 된단 소리니까 set을 사용하면 시간초과가 될 수도 있었을 것 같다.)

반복자도 종류가 있다. 산술 연산이 가능한건 “임의 접근 반복자”를 가지는 vector, deque 밖에 없다.

STL 의 모든 컨테이너 혹은 함수들은 아래와 같은 종류의 반복자들을 지원하는데, 아래 반복자들 중 어느 것들까지 지원을 하느냐에 따라 사용할 수 있는 연산, 함수들이 달라진다.

컨테이너마다 지원하는 반복자의 종류가 다르다.

반복자의 종류

image

image

1️⃣ 입력 반복자(Input)

  • Read 및 접근 만 가능.
  • Write 불가능
  • 증감은 ++ 연산만 가능.
  • 비교는 ==, != 연산만 가능.
cout << itr->size() << endl; // 접근 ⭕
뫄뫄 = *itr;  // 읽기 가능 ⭕ (간접 참조처럼 * 연산자)
itr++; // ++ 연산 가능 ⭕
if (itr1 == itr2); // ⭕
*itr = 뫄뫄;  // 쓰기 불가능 ❌ (간접 참조 수정 불가)


2️⃣ 출력 반복자(Output)

  • Write 만 가능.
  • Read 및 접근 불가능
  • ++ 연산만 가능. (itr++)
  • 비교 연산자 불가능
cout << itr->size() << endl; // 접근 불가능 ❌
뫄뫄 = *itr;  // 읽기 불가능 ❌
itr++; // ++ 연산 가능 ⭕
if (itr1 == itr2); // 비교 연산 불가능 ❌
*itr = 뫄뫄;  // 쓰기 가능 ⭕ 


3️⃣ 순방향 반복자(Forward)

  • 읽기 쓰기 접근 다된다.
  • 산술 연산 👉 ++만 가능
  • 비교 연산 👉 ==, !=만 가능


4️⃣ 양방향 반복자(Bidirectional)

  • 읽기 쓰기 접근 다된다.
  • 산술 연산 👉 ++, -- 가능
  • 비교 연산 👉 ==, !=만 가능

list, set, map 은 이 반복자를 지원한다. (그래서 set 의 반복자끼리 뺄셈을 하려 했을 때 불가능했던 것이다.)

이 양방향 반복자를 지원하지 않는 컨테이너는 알고리즘 헤더의 reverse() 함수를 사용할 수 없다. reverse 함수는 이 양방향 반복자를 사용하기 때문이다. 이처럼 함수, 연산에 따라 사용할 수 있는 반복자가 정해져있다는 것을 꼭 알아두자!


3️⃣ 임의접근 반복자(Random Access))

  • 읽기 쓰기 접근 다된다.
  • 산술 연산 👉 ++, --, ✨+, -, +=, -= 가능✨
  • 비교 연산 👉 ==, !=, ✨>, <, >=, <= 가능✨
  • 첨자 연산자 사용 가능 👉 []
    • itr[n]은 곧 *(itr + n)과도 같다.
      vector<int>::iterator itr;
      itr[4];  // itr 에서 4 칸 더 간 곳의 반복자! 
      

vector, deque 는 이 반복자를 지원한다. 그래서 반복자끼리 사칙연산을 해야한다면 vector를 사용해야 한다.


vector에서의 사용 예시

예시 1

  • itr = container.begin();
    • 첫번째 주소를 받아
  • while (itr != container.end())
    • 반복자가 끝까지 다 돌때까지.
  • *itr
    • 반복자가 가리키는 원소를 이용한 후 (간접참조같이)
  • ++itr 다음 반복자.
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <map>

using namespace std;

int main()
{
	vector<int> container;

	for (int i = 0; i < 10; ++i)
		container.push_back(i);

	vector<int>::const_iterator itr;
	itr = container.begin();
	
	while (itr != container.end())
	{
		cout << *itr << "  ";
		++itr;
	}	
}


예시 2

  • for문 사용
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <map>

using namespace std;

int main()
{
	vector<int> container;

	for (int i = 0; i < 10; ++i)
		container.push_back(i);

	vector<int>::const_iterator itr;
	
	for (auto itr = container.begin(); itr != container.end(); ++itr)
		cout << *itr << "  ";
	cout << endl;
}


예시 3

  • for-each 문 이용
  • for (auto& itr : container)
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <map>

using namespace std;

int main()
{
	vector<int> container;

	for (int i = 0; i < 10; ++i)
		container.push_back(i);

	vector<int>::const_iterator itr;
	
	for (auto& itr : container)
		cout << itr << "  ";
	cout << endl;
}


list에서의 사용 예시

  • list<int> container;
    • push_back 사용
  • 벡터와 동일한 반복자 문법.
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <map>

using namespace std;

int main()
{
	list<int> container;

	for (int i = 0; i < 10; ++i)
		container.push_back(i);

	vector<int>::const_iterator itr;
	
	for (auto& itr : container)
		cout << itr << "  ";
	cout << endl;
}


set에서의 사용 예시

  • set<int> container;
    • insert 사용
  • 벡터와 동일한 반복자 문법.
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <map>

using namespace std;

int main()
{
	set<int> container;

	for (int i = 0; i < 10; ++i)
		container.insert(i);

	vector<int>::const_iterator itr;
	
	for (auto& itr : container)
		cout << itr << "  ";
	cout << endl;
}


map에서의 사용 예시

  • map<int, char> container;
    • insert 사용
      • make_pair 이용하여 key와 value 를 함께 insert 해주기
  • itr → first : Key
  • itr → second : Value
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <map>

using namespace std;

int main()
{
	map<int, char> container;

	for (int i = 0; i < 10; ++i)
		container.insert(make_pair(i, char(i + 65)));

	vector<int>::const_iterator itr;
	
	for (auto& itr : container)
		cout << itr->first << "  " << itr->second << endl;
	cout << endl;
}
💎출력💎

0 A
1 B
2 C
3 D
4 E
5 F
6 G 
7 H
8 I
9 J


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

STL 카테고리 내 다른 글 보러가기

댓글 남기기