나만의 작은 도서관

[C++][STL] 반복자(Iterator) 본문

C++/문법 및 메소드(STL)

[C++][STL] 반복자(Iterator)

pledge24 2025. 3. 13. 23:54

반복자(Iterator)란?

STL 구성 요소

  • STL의 구성 요소(반복자, 컨테이너, 알고리즘) 중 하나.
    • STL은 Standard Template Library의 약자로, C++에서 템플릿을 이용해 정리해 둔 표준 라이브러리를 말한다.
  • 반복자는 원소에 접근할 수 있도록 컨테이너가 내부적으로 들고 있는 포인터 역할을 하는 “객체”이다 (포인터가 아니다)
  • 반복자는 포인터처럼 작동되도록 역참조(*)나 증감 연산자(it++, ++it)와 같은 연산자들이 오버로딩 되어있다.
    • 그냥 포인터랑 정확히 똑같이 작동한다고 생각하면 된다.

iterator

  • 기본 반복자 타입. 
  • begin(), end() 함수가 iterator를 반환한다.
    • begin()는 첫번째 원소를 가리키는 반복자를, end()는 마지막 원소 뒤를 가리키는 반복자를 반환한다.
    • begin(), end() 계열의 함수들은 반복자를 지원하는 각 컨테이너에 정의되어있다.
vector<int> v1 = {1, 2, 3, 4, 5};

vector<int>::iterator it = v1.begin();
for(; it != v1.rend(); it++){
    cout << *it << ' ';
}
cout << '\n';

 

실행 결과

1 2 3 4 5

 

const _iterator

  • const 포인터와 같은 역할을 한다. const_iterator가 가리키고 있는 원소의 값을 수정할 수 없다.
  • cbegin(), cend()가 const_iterator를 반환한다.
    • 각각 begin()과 end()가 반환하는 반복자와 같은 곳을 가리킨다.
vector<int> v1 = {1, 2, 3, 4, 5};

vector<int>::const_iterator c_it = v1.cbegin();
// *c_itr = 10; // 식이 수정할 수 있는 lvalue여야 합니다.

 

reverse_iterator

  • 거꾸로 이동하는 반복자.
  • rbegin(), rend()가 reverse_iterator를 반환한다.
    • rbegin()는 마지막 원소를 가리키는 반복자를, rend()는 첫번째 원소 앞을 가리키는 반복자를 반환한다.
vector<int> v1 = {1, 2, 3, 4, 5};

vector<int>::reverse_iterator r_it = v1.rbegin();
for(; r_it != v1.rend(); r_it++){
    cout << *r_it << ' ';
}
cout << '\n';

 

실행 결과

5 4 3 2 1

 

const_reverse_iterator

  • const 속성을 가진 reverse_iterator 반복자.
  • crbrgin(), crend()가 const_reverse_iterator를 반환한다.
    • 각각 rbegin()과 rend()가 반환하는 반복자와 같은 곳을 가리킨다.
vector<int> v1 = {1, 2, 3, 4, 5};

vector<int>::const_reverse_iterator cr_it = v1.crbegin();
for(; cr_it != v1.rend(); cr_it++){
    cout << *cr_it << ' ';
    // *cr_it = 10; // 식이 수정할 수 있는 lvalue여야 합니다.
}
cout << '\n';

 

실행결과

5 4 3 2 1

 

[C++11] 범위 기반 for문(range based for loop)

  • C++11부터 범위 기반(range-based) for문이 생겼다.
  • 범위 기반 for문은 컨테이너 원소를 for문으로 순차적으로 접근하려 할 때 보다 간단하게 표현할 수 있는 방식이다.
vector<int> v1 = {1, 2, 3, 4, 5};

// "기본적인" 범위 기반 for문(값을 복사하므로 원본은 수정 X)
for(int elem : v1){
    cout << elem << ' ';
}

// "레퍼런스를 사용한" 범위 기반 for문(자주 보이는 패턴)
for(const int& elem : v1){
    cout << elem << ' ';
}

// "auto 타입을 사용한" 범위 기반 for문(개인적으로 별로 안좋아하는 방식)
for(const auto& elem : v1){
    cout << elem << ' ';
}

 


반복자 오버로딩

반복자도 오버로딩이 가능하다. 새로운 클래스에서 반복자를 사용하고 싶은 경우 사용한다.

#include <iostream>
#include <vector>

using namespace std;

class MyContainerIterator 
{
public:
    MyContainerIterator(int* p) : ptr(p) {}

    /* 연산자 오버로딩 */
    int&                    operator*() { return *ptr; }
    MyContainerIterator&    operator++() { ++ptr; return *this; }
    MyContainerIterator     operator++(int) { MyContainerIterator temp = *this; ++ptr; return temp; }
    bool                    operator==(const MyContainerIterator& other) const { return ptr == other.ptr; }
    bool                    operator!=(const MyContainerIterator& other) const { return ptr != other.ptr; }

private:
    int* ptr;
};

class MyContainer 
{
public:
    MyContainer(std::initializer_list<int> init) : data(init) {}

    /* 반복자 begin(), end() 정의*/
    MyContainerIterator begin() { return MyContainerIterator(data.data()); }
    MyContainerIterator end() { return MyContainerIterator(data.data() + data.size()); }

private:
    std::vector<int> data;
};

int main() {
    MyContainer container = {1, 2, 3, 4, 5};

    // 반복자 for 루프
    for (auto it = container.begin(); it != container.end(); ++it)
        cout << *it << " ";
    cout << '\n';

    // 범위 기반 for 루프
    for(auto it : container)
        cout << it << " ";
    cout << '\n';

    return 0;
}

 

실행결과

1 2 3 4 5
1 2 3 4 5

참고자료

https://modoocode.com/223