C++ STL: 3장 - STL 이터레이터

2025. 1. 6. 16:46프로그래밍 언어/C++ STL

3.1 이터레이터의 개념

STL의 이터레이터(Iterator)는 컨테이너와 알고리즘을 연결하는 핵심 도구입니다. 포인터와 유사하게 동작하며, 컨테이너 요소들을 순회하고 조작할 수 있게 해주는 인터페이스입니다.

 

3.2 이터레이터의 유형과 특징

이터레이터는 기능과 동작 방식에 따라 다섯 가지로 구분됩니다:

이터레이터 유형 지원 연산 주요 특징
Input Iterator *, ++ 읽기 전용 (스트림처럼 데이터를 읽고 넘어가면 다시 읽을 수 없다.), 전진만 가능
Output Iterator *, ++ 쓰기 전용, 전진만 가능
Forward Iterator *, ++ 읽기/쓰기 가능, 여러 번 순회 가능
Bidirectional Iterator *, ++, -- 앞뒤로 이동 가능, 읽기/쓰기 가능
Random Access Iterator *, ++, --, +=, [] 임의 위치 접근 가능, 산술 연산 지원

 

3.2.1 Input Iterator

컨테이너의 데이터를 읽기만 할 수 있는 이터레이터입니다.

std::istream_iterator<int> input_iter(std::cin);  // 입력 스트림 이터레이터
std::istream_iterator<int> end;                  // 종료 이터레이터
std::vector<int> numbers(input_iter, end);       // 입력값으로 벡터 초기화

for (const auto& num : numbers) {
    std::cout << num << " ";                     // 읽기만 가능
}

3.2.2 Output Iterator

데이터를 쓰기 위한 이터레이터입니다.

std::vector<int> numbers = {1, 2, 3, 4, 5};

// std::ostream_iterator를 사용한 Output Iterator 예제
std::cout << "Output to console: ";
std::copy(numbers.begin(), numbers.end(),
          std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;

// ostream_iterator: 출력 스트림으로 데이터를 출력하는 이터레이터.

3.2.3 Forward Iterator

한 방향으로만 이동하며 여러 번 순회할 수 있는 이터레이터입니다.

std::forward_list<int> numbers = {1, 2, 3};
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
    *it *= 2;  // 읽기와 쓰기 모두 가능
}

3.2.4 Bidirectional Iterator

양방향으로 이동 가능한 이터레이터입니다.

std::list<int> numbers = {1, 2, 3};
auto it = numbers.end();

while (it != numbers.begin()) {
    --it;  // 뒤로 이동
    std::cout << *it << " ";
}
std::cout << std::endl;

3.2.5 Random Access Iterator

배열처럼 임의의 위치에 직접 접근할 수 있는 이터레이터입니다.

std::vector<int> numbers = {1, 2, 3, 4, 5};
auto it = numbers.begin();
std::cout << it[2];      // 인덱스로 접근
std::cout << *(it + 3);  // 포인터 연산

 

3.3 이터레이터 어댑터

기존 이터레이터에 새로운 기능을 추가한 변형된 이터레이터입니다.

3.3.1 역방향 이터레이터 (Reverse Iterator)

std::vector<int> vec = {1, 2, 3};

// 역방향 이터레이터: 컨테이너의 끝부터 시작으로 역순 순회
for (auto it = vec.rbegin(); it != vec.rend(); ++it) {
    std::cout << *it << " ";  // 3 2 1 순으로 출력
}

3.3.2 삽입 이터레이터 (Insert Iterator)

std::vector<int> vec = {1, 2, 3};
auto insert_it = std::inserter(vec, vec.begin() + 1);
*insert_it = 10;  // 1, 10, 2, 3 순으로 저장

3.3.3 스트림 이터레이터 (Stream Iterator)

std::vector<int> vec = {1, 2, 3};
std::copy(vec.begin(), vec.end(),
    std::ostream_iterator<int>(std::cout, " "));

 

3.4 사용자 정의 이터레이터

필요한 경우 직접 이터레이터를 구현할 수 있습니다.

#include <iostream>
#include <vector>

class CustomIterator {
    int* ptr;

public:
    explicit CustomIterator(int* p) : ptr(p) {}

    int& operator*() { return *ptr; }
    CustomIterator& operator++() {
        ++ptr;
        return *this;
    }
    bool operator!=(const CustomIterator& other) const { return ptr != other.ptr; }
};

int main() {
    int arr[] = {1, 2, 3, 4};
    CustomIterator begin(arr), end(arr + 4);

    while (begin != end) {
        std::cout << *begin << " ";
        ++begin;
    }
    return 0;
}

 

활용

  • 가능하면 범위 기반 for문을 사용하세요.
for (const auto& elem : container) { ... }
  • auto를 활용해 복잡한 이터레이터 타입 선언을 간단히 하세요.
auto it = container.begin();
  • 읽기 전용 작업에는 const_iterator를 사용하세요.
for (auto it = container.cbegin(); it != container.cend(); ++it)

 

다음 장에서는 이터레이터와 함께 사용하는 STL 알고리즘에 대해 살펴보겠습니다.