본문 바로가기
개발/C++ (98,03,11,14,17,20,23)

Modern C++ : iterators (98, 11, 17, 20)

by snowoods 2025. 8. 27.

Modern C++

Iterators in C++

 

개요

Iterator는 C++ STL(Standard Template Library)에서 컨테이너의 요소들을 순회하고 접근하기 위한 추상화된 방법을 제공하는 객체입니다. 포인터와 유사한 동작을 하지만, 컨테이너의 내부 구현을 캡슐화하여 일관된 인터페이스를 제공합니다.

 

C++ 버전별 주요 키워드 도입 시기

  • C++98: 기본 반복자 개념 도입
  • C++11: cbegin(), cend(), crbegin(), crend() 추가
  • C++17: std::size(), std::empty(), std::data() 등 반복자 관련 유틸리티 추가
  • C++20: std::ranges 도입으로 더 나은 반복자 지원

 

내용 설명

반복자 카테고리

  1. 입력 반복자 (Input Iterator): 읽기 전용, 순방향 이동만 가능
  2. 출력 반복자 (Output Iterator): 쓰기 전용, 순방향 이동만 가능
  3. 순방향 반복자 (Forward Iterator): 입력/출력 모두 가능, 순방향 이동만 가능
  4. 양방향 반복자 (Bidirectional Iterator): 순방향/역방향 이동 가능
  5. 임의 접근 반복자 (Random Access Iterator): 임의의 위치로 즉시 이동 가능

 

주요 반복자 연산

  • *iter: 현재 요소에 접근
  • iter->member: 현재 요소의 멤버에 접근
  • ++iter, iter++: 다음 요소로 이동
  • --iter, iter--: 이전 요소로 이동 (Bidirectional 이상)
  • iter + n, iter - n: n번째 다음/이전 요소로 이동 (Random Access)
  • iter1 - iter2: 두 반복자 사이의 거리 (Random Access)

 

예제 코드

#include <iostream>
#include <iterator>
#include <vector>

template <typename T>
void print_vector(const std::vector<T> &vec) {
    std::cout << "Printing vectors values:\n";
    for (const auto v : vec) {
        std::cout << v << '\n';
    }
    std::cout << '\n';
}

int main() {
    // 벡터 초기화
    auto my_vector = std::vector{0, 1, 2, 3, 4, 5};

    // 1. ForwardIterator 예제
    auto it1 = my_vector.begin();
    auto it2 = my_vector.end();
    for (; it1 != it2; ++it1) {
        *it1 = 1;  // 값 수정
    }
    print_vector(my_vector);

    // 2. BidirectionalIterator 예제 (역방향 순회)
    auto it3 = my_vector.rbegin();
    auto it4 = my_vector.rend();
    for (; it3 != it4; ++it3) {
        *it3 = 2;  // 값 수정
    }
    print_vector(my_vector);

    // 3. Const 반복자 (수정 불가)
    auto it5 = my_vector.cbegin();
    auto it6 = my_vector.cend();
    // *it5 = 3;  // 컴파일 오류: 수정 불가

    // 4. 반복자 유틸리티 함수들
    auto vec_it = my_vector.begin();  // 첫 번째 요소 가리킴
    std::advance(vec_it, 2);         // 2칸 전진
    std::cout << "Vector[2] = " << *vec_it << '\n';

    // 거리 계산
    auto dist1 = std::distance(vec_it, my_vector.end());
    auto dist2 = std::distance(my_vector.begin(), vec_it);
    std::cout << "Distance to end: " << dist1 
              << " Distance from begin: " << dist2 << '\n';

    // 이전/다음 요소 접근
    auto prev = std::prev(vec_it);
    std::cout << "Previous value: " << *prev << '\n';
    auto next = std::next(vec_it);
    std::cout << "Next value: " << *next << '\n';

    return 0;
}

 

실행 결과

Printing vectors values:
1
1
1
1
1
1

Printing vectors values:
2
2
2
2
2
2

Vector[2] = 2
Distance to end: 4 Distance from begin: 2
Previous value: 2
Next value: 2

 

활용팁

  1. const 반복자 사용: 컨테이너를 수정하지 않을 때는 cbegin(), cend()를 사용하면 실수로 값을 변경하는 것을 방지할 수 있습니다.
  2. 범위 기반 for 루프: C++11부터 도입된 범위 기반 for 루프를 사용하면 반복자 사용을 간소화할 수 있습니다.
  3. auto 키워드: 반복자 타입이 길고 복잡할 수 있으므로 auto를 사용하는 것이 좋습니다.
  4. 반복자 무효화: 컨테이너가 수정될 때(요소 추가/삭제 등) 반복자가 무효화될 수 있으므로 주의가 필요합니다.
  5. <algorithm> 헤더 활용: 대부분의 알고리즘은 반복자를 사용하므로 <algorithm> 헤더의 함수들과 함께 사용하면 강력한 기능을 구현할 수 있습니다.