C++ iterator | "Iterator" Complete Guide
이 글의 핵심
An iterator walks container elements. Use begin/end with range-for and vector; pair with size_t and ptrdiff_t for distances; unify tree walks with the Composite pattern.
Iterator Basics
Iterator is an object that iterates over container elements. It is used as begin/end in range-based for and vector, and is often used when dealing with distance and index with size_t·ptrdiff_t and when unifying tree traversal with Composite pattern I write.
Iterator concept diagram```mermaid
graph LR A[Container] —> B[begin] A —> C[end]
B --> D[Iter]
D -->|++| E[Iter]
E -->|++| F[Iter]
F -->|++| C
D -->|*| G[Elem 1]
E -->|*| H[Elem 2]
F -->|*| I[Elem 3]
```cpp
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
// begin/end
for (auto it = v.begin(); it != v.end(); ++it) {
cout << *it << " ";
}
cout << endl;
// 역방향
for (auto it = v.rbegin(); it != v.rend(); ++it) {
cout << *it << " "; // 5 4 3 2 1
}
}
```## Iterator type
### Iterator Hierarchy```mermaid
graph TD
A[Input Iterator] --> C[Forward Iterator]
B[Output Iterator] --> C
C --> D[Bidirectional Iterator]
D --> E[Random Access Iterator]
E --> F[Contiguous Iterator C++20]
A -.->|읽기 전용| A1[istream_iterator]
B -.->|쓰기 전용| B1[ostream_iterator]
C -.->|단방향| C1[forward_list]
D -.->|양방향| D1[list, set, map]
E -.->|임의 접근| E1[vector, deque, array]
F -.->|연속 메모리| F1[vector, array, string]
```### Iterator function comparison table
| iterator type | Read | writing | Forward | Reverse | random access | Example container |
|-------------|------|------|------|------|-----------|---------------|
| Input | ✅ | ❌ | ✅ | ❌ | ❌ | `istream_iterator` |
| Output | ❌ | ✅ | ✅ | ❌ | ❌ | `ostream_iterator` |
| Forward | ✅ | ✅ | ✅ | ❌ | ❌ | `forward_list` |
| Bidirectional | ✅ | ✅ | ✅ | ✅ | ❌ | `list`, `set`, `map` |
| Random Access | ✅ | ✅ | ✅ | ✅ | ✅ | `vector`, `deque` |
### Input Iterator```cpp
// 읽기 전용, 한 번만 순회
istream_iterator<int> in(cin);
istream_iterator<int> eof;
vector<int> v(in, eof); // 입력 읽기
Output Iterator
// 쓰기 전용
ostream_iterator<int> out(cout, " ");
vector<int> v = {1, 2, 3};
copy(v.begin(), v.end(), out); // 1 2 3
Forward Iterator
// 읽기/쓰기, 여러 번 순회
forward_list<int> fl = {1, 2, 3};
for (auto it = fl.begin(); it != fl.end(); ++it) {
*it *= 2;
}
Bidirectional Iterator
// 양방향 이동
list<int> l = {1, 2, 3, 4, 5};
auto it = l.end();
--it; // 마지막 원소
cout << *it << endl; // 5
Random Access Iterator
// 임의 접근
vector<int> v = {1, 2, 3, 4, 5};
auto it = v.begin();
it += 3; // 3칸 이동
cout << *it << endl; // 4
cout << v[2] << endl; // 3
```## Practical example
### Example 1: Custom iterator```cpp
class Range {
private:
int current;
int end;
public:
class Iterator {
private:
int value;
public:
using iterator_category = forward_iterator_tag;
using value_type = int;
using difference_type = ptrdiff_t;
using pointer = int*;
using reference = int&;
Iterator(int v) : value(v) {}
int operator*() const { return value; }
Iterator& operator++() {
++value;
return *this;
}
bool operator!=(const Iterator& other) const {
return value != other.value;
}
};
Range(int start, int end) : current(start), end(end) {}
Iterator begin() { return Iterator(current); }
Iterator end() { return Iterator(this->end); }
};
int main() {
for (int x : Range(0, 10)) {
cout << x << " "; // 0 1 2 ... 9
}
}
```### Example 2: Filter iterator```cpp
template<typename Iter, typename Pred>
class FilterIterator {
private:
Iter current;
Iter end;
Pred predicate;
void advance() {
while (current != end && !predicate(*current)) {
++current;
}
}
public:
FilterIterator(Iter begin, Iter end, Pred pred)
: current(begin), end(end), predicate(pred) {
advance();
}
auto operator*() const { return *current; }
FilterIterator& operator++() {
++current;
advance();
return *this;
}
bool operator!=(const FilterIterator& other) const {
return current != other.current;
}
};
int main() {
vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto isEven = { return x % 2 == 0; };
FilterIterator begin(v.begin(), v.end(), isEven);
FilterIterator end(v.end(), v.end(), isEven);
for (auto it = begin; it != end; ++it) {
cout << *it << " "; // 2 4 6 8 10
}
}
```### Example 3: Conversion Iterator```cpp
template<typename Iter, typename Func>
class TransformIterator {
private:
Iter current;
Func transform;
public:
TransformIterator(Iter it, Func f) : current(it), transform(f) {}
auto operator*() const {
return transform(*current);
}
TransformIterator& operator++() {
++current;
return *this;
}
bool operator!=(const TransformIterator& other) const {
return current != other.current;
}
};
int main() {
vector<int> v = {1, 2, 3, 4, 5};
auto square = { return x * x; };
TransformIterator begin(v.begin(), square);
TransformIterator end(v.end(), square);
for (auto it = begin; it != end; ++it) {
cout << *it << " "; // 1 4 9 16 25
}
}
```## Iterator operations
### Iterator operation function comparison
| function | Time Complexity | Support iterators | Description |
|------|-------------|-------------|------|
| **advance(it, n)** | O(1) ~ O(N) | all iterators | Move n spaces (Modify position) |
| **distance(first, last)** | O(1) ~ O(N) | Input or more | Distance between two iterators |
| **next(it, n=1)** | O(1) ~ O(N) | Forward or more | Return iterator n spaces ahead |
| **prev(it, n=1)** | O(1) ~ O(N) | Bidirectional ideal | return iterator after n spaces |
| **iter_swap(it1, it2)** | O(1) | Forward or more | Swap two iterator values |```cpp
vector<int> v = {1, 2, 3, 4, 5};
auto it = v.begin();
// 전진
advance(it, 3); // 3칸 이동
cout << *it << endl; // 4
// 거리
auto dist = distance(v.begin(), v.end());
cout << dist << endl; // 5
// 다음/이전
auto next_it = next(it);
auto prev_it = prev(it);
```**advance vs next difference**:```mermaid
graph LR
A[it = v.begin] --> B{Which?}
B -->|advance it, 3| C[Modify it]
C --> D[it = begin+3]
B -->|next it, 3| E[Return new]
E --> F[it = begin]
E --> G[return = begin+3]
```## Frequently occurring problems
### Problem 1: Invalidated Iterators```cpp
// ❌ 반복자 무효화
vector<int> v = {1, 2, 3, 4, 5};
for (auto it = v.begin(); it != v.end(); ++it) {
if (*it == 3) {
v.erase(it); // it 무효화!
// ++it; // 위험!
}
}
// ✅ erase 반환값 사용
for (auto it = v.begin(); it != v.end();) {
if (*it == 3) {
it = v.erase(it); // 다음 반복자 반환
} else {
++it;
}
}
```### Problem 2: end() dereference```cpp
// ❌ end() 역참조
vector<int> v = {1, 2, 3};
auto it = v.end();
// cout << *it << endl; // UB
// ✅ end() 체크
if (it != v.end()) {
cout << *it << endl;
}
```### Problem 3: Iterator type mismatch```cpp
// ❌ 타입 불일치
vector<int> v;
list<int> l;
// auto it = v.begin();
// it = l.begin(); // 에러
// ✅ 올바른 타입
auto vit = v.begin();
auto lit = l.begin();
iterator_traits
template<typename Iter>
void printIteratorInfo() {
using traits = iterator_traits<Iter>;
cout << "value_type: " << typeid(typename traits::value_type).name() << endl;
cout << "difference_type: " << typeid(typename traits::difference_type).name() << endl;
cout << "iterator_category: " << typeid(typename traits::iterator_category).name() << endl;
}
int main() {
printIteratorInfo<vector<int>::iterator>();
}
```## FAQ
### Q1: When do you use iterators?
**A**:
- Container traversal
- STL algorithm
- Specify scope
### Q2: Pointer vs Iterator?
**A**: Iterators are more abstract and safer.
### Q3: What about iterator invalidation?
**A**:
- vector: When inserting/deleting
- list: only deleted elements
- map: only deleted elements
### Q4: What about custom iterators?
**A**: Requires implementation of 5 typedefs and operators.
### Q5: What is the iterator performance?
**A**: Inlined, similar to a pointer.
### Q6: What are the iterator learning resources?
**A**:
- "Effective STL" (Scott Meyers)
- cppreference.com
- "The C++ Standard Library"
**Related posts**: [Range-based for](/blog/cpp-range-based-for/), [Vector complete guide](/blog/cpp-stl-vector-complete/), [size_t·ptrdiff_t](/blog/cpp-size-t-ptrdiff-t/), [Composite pattern](/blog/cpp-composite-pattern/).
---
## Good article to read together (internal link)
Here's another article related to this topic.
- [C++ range-based for | "Range-based for" guide](/blog/cpp-range-based-for/)
- [C++ STL vector | "Easier than arrays" Complete vector summary [Practical example]](/blog/cpp-stl-vector-complete/)
- [C++ size_t & ptrdiff_t | “Size Type” Guide](/blog/cpp-size-t-ptrdiff-t/)
- [Complete Guide to C++ Composite Pattern | Treating the tree structure as the same interface](/blog/cpp-composite-pattern/)
## Practical tips
These are tips that can be applied right away in practice.
### Debugging tips
- If you run into a problem, check the compiler warnings first.
- Reproduce the problem with a simple test case
### Performance Tips
- Don't optimize without profiling
- Set measurable indicators first
### Code review tips
- Check in advance for areas that are frequently pointed out in code reviews.
- Follow your team's coding conventions
---
## Practical checklist
This is what you need to check when applying this concept in practice.
### Before writing code
- [ ] Is this technique the best way to solve the current problem?
- [ ] Can team members understand and maintain this code?
- [ ] Does it meet the performance requirements?
### Writing code
- [ ] Have you resolved all compiler warnings?
- [ ] Have you considered edge cases?
- [ ] Is error handling appropriate?
### When reviewing code
- [ ] Is the intent of the code clear?
- [ ] Are there enough test cases?
- [ ] Is it documented?
Use this checklist to reduce mistakes and improve code quality.
---
## Keywords covered in this article (related search terms)
This article will be helpful if you search for C++, iterator, iterator, STL, range, etc.
---
## Related articles
- [C++ iterator invalidation error | ](/blog/cpp-error-05-iterator-invalidation/)
- [A complete guide to C++ iterator basics | iterator category·begin/end·reverse iterator·practical pattern](/blog/cpp-series-17-1-iterator-basics/)
- [C++ Custom Iterator Complete Guide | Forward·Bidirectional](/blog/cpp-series-17-2-custom-iterator/)
- [C++20 Ranges | Escaping the begin/end loop and writing the ranges algorithm](/blog/cpp-series-25-1-ranges-basics/)
- [C++ Tag Dispatch Complete Guide | Compile-time function selection and STL optimization](/blog/cpp-tag-dispatch/)