vector
- 크기가 자유롭게 늘어나는 배열
일반적인 배열 int arr[]는 처음에 정한 크기를 바꿀 수 없다.
하지만 vector는 데이터가 꽉 차면 스스로 덩치를 키운다.
iterator
한문장 정리: 컨테이너 안의 원소를 가리키는 '포인터 비슷한 것'
- 인덱스가 아니고, 위치를 나타냄
이건 vector v의 첫 번째 원소 위치를 가리키는 변수이다.
포인터는 메모리 주소를 직접 접근하는 것에 목적이 있지만,
이터레이터는 컨테이너를 추상화해서 다루는 장비이다.
*it // 값 접근
++it // 다음 원소
it1 == it2 // 같은 위치인지
vector<int> v={1,2,3,4,5};
for (auto it = v.begin(); it != v.end(); ++it) {
cout << *it << '\n';
}
//원소 모두 출력
//주의할 점: v.end()는 마지막 원소의 다음 위치! 그래서 *(v.end())는 errorv.begin(): 벡터의 첫 번째 데이터를 가리킵니다.
v.end(): 벡터의 마지막 데이터 바로 뒤를 가리킵니다. (데이터가 없는 끝 지점입니다.)
++it: 화살표를 다음 칸으로 한 칸 옮깁니다.
*it: 현재 화살표가 가리키고 있는 칸에 들어있는 실제 숫자를 꺼냅니다.
컨테이너에 따른 이터레이터 연산 가능/불가능
Q&A
1. iterator의 타입은 주소값이야?
it1 == it2는 같은 주소인지 비교하는 거야?
짧은 답
논리적으로는 ‘같은 위치’ 비교고, 구현상은 주소일 수도 있고 아닐 수도 있음.
조금 풀어서
- iterator는 주소값 그 자체라고 약속된 적은 없음
- 하지만
vector, 배열 같은 경우는 내부적으로 진짜 포인터처럼 구현되는 경우가 많음
그래서:
it1 == it2
의 의미는
“같은 컨테이너의 같은 원소를 가리키고 있나?”
이지
“메모리 주소 숫자가 같나?”
는 아님 (결과는 비슷해 보일 수 있지만 개념은 다름).
예를 들어:
vector<int>::iterator→ 거의 포인터map<int,int>::iterator→ 트리 노드를 감싼 객체
둘 다 ==는 되지만
주소 비교라는 개념으로 생각하면 바로 오해 생김.
👉 안전한 사고 방식:
iterator는 ‘주소처럼 행동하는 추상 객체’라고 생각해라.
2. ++i는 전위 연산자잖아?
그럼 ++it는 왜 다음 원소고, it++는 왜 안 쓰는 거야?
핵심부터
++it와it++둘 다 다음 원소로 이동함- 하지만 의미와 비용이 다름
전위 증가 (++it)
++it;
- 먼저 증가
- 증가된 iterator를 반환
- 불필요한 복사 없음
후위 증가 (it++)
it++;
- 증가 전 iterator를 복사
- 그 복사본을 반환
- 그 다음 실제 iterator 증가
즉 내부적으로:
auto temp = it;
++it;
return temp;
이런 느낌.
그래서 왜 ++it를 쓰냐
- iterator는 객체라서 복사가 비용일 수 있음
- 특히
map,setiterator는 가볍지 않음 - STL 관례상 의미 없는 복사를 피하자는 문화
그래서:
“증가만 필요하면 무조건
++it”
이건 거의 C++ 계의 암묵적 헌법임.
3. 컨테이너마다 가능한 iterator 연산이 다른 거야?
정확히 그렇다.
이게 iterator 등급 개념의 핵심임.
예시로 보면 바로 감 옴
vector (random access iterator)
it + 5
it - 3
it2 - it1
it < it2
전부 가능.
list (bidirectional iterator)
++it
--it
이건 되는데
it + 3 // 컴파일 에러
안 됨.
forward_list (forward iterator)
++it
만 가능.
--it // 불가
그래서 STL 알고리즘도 제약이 있음:
| 알고리즘 | 요구 iterator |
|---|---|
| sort | random access |
| lower_bound | 최소 forward (속도 차이 큼) |
| reverse | bidirectional |
| find | input iterator |
👉 컴파일 에러가 나면 “내가 틀린 게 아니라 컨테이너가 못 하는 거일 수도 있음”
4. 컨테이너 종류를 바꿀 수 있는 거야?
정의할 때 이미 정해지는 거 아니야?
이 질문이 진짜 중요하다.
물리적으로는
vector<int> v;
하면
이 변수는 영원히 vector임.
list로 변신 안 함. 초능력 없음.
그런데 “바꿀 수 있다”는 말의 진짜 의미
코드를 거의 안 바꾸고, 컨테이너만 교체할 수 있게 설계 가능하다는 뜻.
예:
template <typename Container>
void print_all(Container& c) {
for (auto it = c.begin(); it != c.end(); ++it)
cout << *it << ' ';
}
이 함수는:
- vector
- list
- deque
- set
전부 받아먹음.
왜?
- iterator 인터페이스가 같기 때문.
반대로 이런 코드는 바꾸기 힘듦
for (int i = 0; i < v.size(); i++) {
cout << v[i];
}
이건:
- vector 전용
- list로 바꾸는 순간 전멸
그래서 STL 철학이 이거임
“컨테이너는 바뀔 수 있고,
알고리즘은 iterator 위에서 동작한다.”
이게 왜 좋냐면:
- 처음엔 vector
- 나중에 성능 문제 생기면 list / deque / set으로 교체
- 로직은 거의 그대로
'프로그래밍 공부 > C++' 카테고리의 다른 글
| STL stack, queue, priority queue (0) | 2026.01.19 |
|---|---|
| STL - set, unordered_set, map, unordered_map (0) | 2026.01.19 |
| STL - deque 자주 쓰는 함수 (0) | 2026.01.17 |
| STL - list 자주 쓰는 메소드 (0) | 2026.01.17 |
| STL 알아보기 Vector, list, deque, array (0) | 2026.01.17 |