Custom Iterator Utilities in C++
개요
이 문서는 C++ 표준 라이브러리의 반복자 유틸리티 함수들을 직접 구현한 예제를 다룹니다. advance
, distance
, next
, prev
함수들을 구현하여 반복자의 동작 방식을 이해하고, 이를 활용하는 방법을 설명합니다.
C++ 버전별 주요 키워드 도입 시기
- C++98: 기본 반복자 유틸리티 도입
- C++11:
std::next()
,std::prev()
함수 추가 - C++17:
std::size()
와 같은 반복자 관련 유틸리티 추가 - C++20:
std::ranges
와 함께 개선된 반복자 지원
내용 설명
구현된 타입과 함수들
DifferenceType
- 반복자 간의 거리를 표현하는 정수 타입입니다.
- 실제 정의:
using DifferenceType = It::difference_type;
It
은std::vector<std::int32_t>::iterator
의 별칭입니다.std::vector
의 반복자는random_access_iterator
이므로,difference_type
은std::ptrdiff_t
와 동일한 타입입니다.std::ptrdiff_t
는 두 포인터 간의 차이를 저장할 수 있는 부호 있는 정수 타입입니다.<cstddef>
헤더에 정의되어 있으며, 포인터 연산의 결과를 저장하기에 충분한 크기를 가집니다.- 32비트 시스템에서는 일반적으로 4바이트, 64비트 시스템에서는 8바이트 크기입니다.
sizeof(std::ptrdiff_t) == sizeof(void*)
가 일반적입니다.
std::iterator_traits<It>::difference_type
에서도 동일한 타입을 얻을 수 있습니다.- 반복자 간의 거리나 이동 거리를 표현할 때 사용됩니다.
- 부호 있는 정수 타입으로, 양수와 음수 모두 표현 가능합니다.
- 실제 크기는 플랫폼에 따라 다르지만, 일반적으로 64비트 시스템에서는 8바이트(64비트) 크기를 가집니다.
주요 함수들
- advance
- 반복자를 n만큼 전진 또는 후진시킵니다.
- 양수 n: 앞으로 n칸 이동
- 음수 n: 뒤로 n칸 이동
- distance
- 두 반복자 사이의 거리를 반환합니다.
- 첫 번째 반복자부터 두 번째 반복자까지의 요소 수를 계산합니다.
- next
- 현재 반복자에서 n칸 앞에 있는 반복자를 반환합니다.
- 기본값으로 1칸 앞의 반복자를 반환합니다.
- prev
- 현재 반복자에서 n칸 뒤에 있는 반복자를 반환합니다.
- 기본값으로 1칸 뒤의 반복자를 반환합니다.
예제 코드
#include <cstdint>
#include <iterator>
#include <vector>
namespace mystd
{
using It = std::vector<std::int32_t>::iterator;
using DifferenceType = It::difference_type;
void advance(It &it, DifferenceType n)
{
while (n > 0)
{
++it;
--n;
}
while (n < 0)
{
--it;
++n;
}
}
DifferenceType distance(It first, It last)
{
auto result = DifferenceType{0};
while (first != last)
{
++first;
++result;
}
return result;
}
It next(It it, DifferenceType n = 1)
{
mystd::advance(it, n);
return it;
}
It prev(It it, DifferenceType n = 1)
{
mystd::advance(it, -n);
return it;
}
} // namespace mystd
실행 예제
#include <iostream>
#include <vector>
int main()
{
std::vector<int> vector{1, 2, 3};
auto vector_it = vector.begin();
// next 사용 예제
auto next_it = mystd::next(vector_it);
std::cout << "*next_it: " << *next_it << '\n'; // 출력: 2
// prev 사용 예제
auto prev_it = mystd::prev(next_it);
std::cout << "*prev_it: " << *prev_it << '\n'; // 출력: 1
// advance 사용 예제
mystd::advance(vector_it, 2);
std::cout << "advance: " << *vector_it << '\n'; // 출력: 3
// distance 사용 예제
auto dist = mystd::distance(vector.begin(), vector_it);
std::cout << "distance: " << dist << '\n'; // 출력: 2
return 0;
}
실행 결과
*next_it: 2
*prev_it: 1
advance: 3
distance: 2
활용팁
- 성능 고려사항
distance
함수는 선형 시간(O(n))이 소요될 수 있으므로, 임의 접근 반복자에서는 사용을 지양하고-
연산자를 사용하는 것이 좋습니다.
- 안전성
advance
함수는 컨테이너의 범위를 벗어나는지 검사하지 않으므로 주의가 필요합니다.- 범위 기반 for 문이나 표준 알고리즘을 사용할 수 있다면, 직접 반복자를 다루는 것보다 이를 우선적으로 고려하세요.
- 템플릿 활용
- 이 예제는
std::vector<int>
에 특화되어 있지만, 템플릿을 사용하면 다양한 컨테이너에 적용 가능한 일반적인 구현이 가능합니다.
- 이 예제는
- 디버깅
- 복잡한 반복자 연산 시 중간 결과를 확인하기 위해
std::distance
와 같은 함수를 활용하여 디버깅할 수 있습니다.
- 복잡한 반복자 연산 시 중간 결과를 확인하기 위해
'개발 > C++ (98,03,11,14,17,20,23)' 카테고리의 다른 글
Modern C++ : std::inserter (98, 11, 17) (1) | 2025.08.28 |
---|---|
Modern C++ : iterators (98, 11, 17, 20) (0) | 2025.08.27 |
Modern C++ : type aliases (typedef and using) (98, 11) (0) | 2025.08.26 |
Modern C++ : std::map (98, 11, 17, 20) (0) | 2025.08.25 |
Modern C++ : std::pair, std::tuple (98, 11, 17) (0) | 2025.08.24 |
Modern C++ : std::span (20) (1) | 2025.08.23 |
Modern C++ : std::vector, emplace_back vs push_back (98, 11, 17) (0) | 2025.08.22 |
Modern C++ : std::vector (98, 11, 14, 17, 20) (0) | 2025.08.21 |