치춘짱베리굿나이스
[Rank 5] ft_containers - std::reverse_iterator 본문
먼저 읽어보고 오세요
[Rank 5] ft_containers - std::iterator_traits
iterator_category
에서 양방향 반복자와 임의접근 반복자가 무엇인지 간단하게나마 알고 오면 조금 더 쉽다!!
뭐하는 친구인가요
42를 하는 한국인이라면 익숙할 노선도이다 (버스 타는 사람이나 대모산입구 쪽에서 오는 사람은 죄송)
이때 지하철을 반복자, 선릉 ~ 개포동을 분당선 컨테이너 내의 요소들이라고 생각해보자
- 지하철은 선릉에서 출발하여 한티, 도곡, 구룡을 거쳐 개포동에 도착한다
- = 반복자는 ‘선릉’ 요소에서 ‘개포동’ 요소까지의 범위 (range) 를 순회한다
- 이 방향을 ‘순방향’ 이라고 가정하자
- 하지만 집에 가고 싶을 땐 선릉에서 개포동 방향으로 나아가는 지하철을 탔다간 집과 정반대인 수원이나 인천 방향으로 빠져버린다
- 이 때는 선릉에서 개포동으로 가는 열차 대신, 개포동에서 선릉으로 가는 열차를 타야 한다
- 선릉에서 개포동으로 가는 열차가 정방향 반복자였다면, 개포동에서 선릉으로 가는 열차는 역방향 반복자 (
reverse_iterator
) 가 된다
특징
- 역방향 반복자는 정방향 반복자와 반대 방향으로 동작한다
- 증가 (
+
,++
) 연산자는 정방향 반복자의 시점에서 감소하는 방향으로 움직인다 - 감소 (
-
,—-
) 연산자는 정방향 반복자의 시점에서 증가하는 방향으로 움직인다 +
,-
연산자도 마찬가지로 역방향으로 동작한다
- 증가 (
- 정방향 반복자의 시작점이
begin()
이었다면, 역방향 반복자의 시작점은rbegin()
이다 - 정방향 반복자의 끝점이
end()
였다면, 역방향 반복자의 끝점은rend()
이다 begin()
은rend()
보다 한 칸 앞이다end()
는rbegin()
보다 한 칸 뒤이다
멤버 변수와 생성자
기본 반복자
base iterator
라고도 한다
기본 반복자는 원래 정방향으로 움직이던 반복자로, 개포동 → 선릉 노선 (수서행) 을 만들기 위해 선릉 → 개포동 노선 (왕십리행) 을 뼈대 삼아 구축하는 것이라고 생각하면 된다
생성자 단계에서 인자로 받아, 내부적으로 복사하여 저장한다
복사된 반복자는 reverse_iterator
내부 멤버 함수를 호출할 때마다 가리키는 요소가 변경되는 실질적 객체이며, 결과적으로 역방향 반복자는 정방향 반복자를 복사한 뒤 동작만 거꾸로 한 것이라고 볼 수 있다
생성자
reverse_iterator(); // 기본 생성자
explicit reverse_iterator(iterator_type it); // 초기화 생성자
template <class Iter>
reverse_iterator(const reverse_iterator<Iter>& rev_it); // 복사 + 타입 캐스트 생성자
- 기본 생성자
- 어떠한 인자도 받지 않는 쌩 기본 생성자이다
- 기본 반복자 (
base_iterator
) 가 초기화되지 않는다
- 초기화 생성자
- 기본 반복자를 인자로 받아 멤버 변수로 저장하는 역할을 한다
- 강제 형변환을 막아주는
explicit
키워드가 사용되었다
- 복사 생성자
- 기존의
reverse_iterator
를 복사한다 - 기존의 반복자를 복사하므로, 내부의 멤버 변수인 기본 반복자도 복사된다
- 기존의
멤버 함수들
base
iterator_type base() const {
return _base_it; // 기본이 되는 반복자 = base iterator 반환
}
기본이 되는 반복자를 반환한다
기본이 되는 반복자 (base iterator
) 는 원래 정방향으로 움직이던 반복자를 생성자 단계에서 멤버 변수로 저장해둔 것이다
역방향 반복자도 내부적으로는 기본 반복자가 (역방향으로) 움직이는 방식으로 구현된다
(아님)
operator*
reference operator*() const;
*
연산자에 대한 오버로드*
연산자는 요소의 참조를 반환할 때 사용된다
- 클래스 내의 요소를 변경하지 않으므로
const
가 붙는다 - 구현을 할 때 주의해야 할 점으로
- 겉으로 보기엔
rbegin()
이 정방향 반복자의end()
보다 한칸 앞을 가리키는 것처럼 보인다 - 허나 내부 구현상 정방향 반복자의
end()
가 역방향 반복자의begin()
(=rbegin()
) 과 같기 때문에 실제로는 가리키고자 하는 요소의 한 칸 뒤를 가리키게 된다 - 따라서 기본 반복자 (base iterator) 를 반환 전에 내부적으로 포인터 위치를 한 칸 앞으로 당겨주어야 한다는 것을 명심하자
- 겉으로 보기엔
operator→
pointer operator->() const;
->
연산자에 대한 오버로드->
연산자는 요소의 참조를 반환할 때 사용된다
- 클래스 내의 요소를 변경하지 않으므로
const
가 붙는다 *
연산자와 마찬가지로 기본 반복자가 실제 요소의 한 칸 뒤를 가리키므로,*
연산자 오버로드를 호출하여 그 포인터를 가져오거나, 현재 기본 반복자의 한 칸 앞을 반환하는 방식으로 구현해야 한다
operator[]
reference operator[](difference_type n) const;
[]
연산자에 대한 오버로드- 특정 인덱스의 요소 (의 참조) 에 접근하고자 할 때 사용하는 연산자이다 (
arr[1]
과 같은 식) - 마찬가지로 실제 인덱스에서 한 칸 앞의 요소를 반환해야 한다
operator++
reverse_iterator operator++();
++
연산자 (전위) 에 대한 오버로드- 역방향 연산자의 방향에 유의하여 구현하자
operator++ (int)
reverse_iterator operator++(int);
++
연산자 (후위) 에 대한 오버로드- CPP 02에서 후위연산자 오버로드를 처음 구현했을 때 반환값을 임시 저장했던 것을 기억하자
- 후위연산이기 때문에, 해당 라인의 모든 다른 연산이 끝난 후 기본 반복자 (base iterator) 가 수정되어야 한다는 점에 유의
operator+=
reverse_iterator& operator+=(difference_type n);
+=
연산자에 대한 오버로드difference_type
는 반복자가 가리키는 한 칸의 크기와 같다 (= 포인터가 가리키는 메모리 영역의 크기, 포인터를 한 칸 이동시켰을 때 실제로 이동하는 메모리의 크기)
operator+
reverse_iterator operator+(difference_type n);
+
연산자에 대한 오버로드
operator—
everse_iterator operator--()
--
연산자 (전위) 에 대한 오버로드++
연산자와 마찬가지로 역방향 반복자의 방향에 유의하자
operator—
reverse_iterator operator--(int);
--
연산자 (후위) 에 대한 오버로드++
연산자 (후위) 와 구현법이 동일하되 방향만 다르다
operator-=
reverse_iterator& operator-=(difference_type n) const;
-=
연산자에 대한 오버로드
operator-
reverse_iterator operator-(difference_type n) const;
-
연산자에 대한 오버로드
비 멤버 함수 오버로드
operator+
reverse_iterator<Iterator> operator+(typename reverse_iterator<Iterator>::difference_type n, const reverse_iterator<Iterator>& it);
- 한 반복자를
n
만큼 증가시킬 때 사용하는 덧셈 연산자 오버로드 - 반복자가 연산자의 왼쪽에 있는 경우 (정수
n
이 오른쪽) 는 멤버 함수 내에 + 연산자 오버로드로 구현하고, 정수가 연산자의 왼쪽에 있는 경우는 비 멤버 오버로드로 구현해야 한다
operator-
reverse_iterator<InputIt1>::difference_type operator-(const reverse_iterator<InputIt1>& lhs, const reverse_iterator<InputIt2>& rhs)
- 두 반복자
lhs
,rhs
간의 간격 (차이) 을 나타내는 뺄셈 연산자 오버로드lhs
: left-hand side, 연산자 기준 왼쪽rhs
: right-hand side, 연산자 기준 오른쪽
operator==
bool operator==(const reverse_iterator<InputIt1>& lhs, const reverse_iterator<InputIt2>& rhs);
- 두 반복자
lhs
,rhs
의 같음 여부를 판단하는 등호 연산자 오버로드
operator!=
bool operator!=(const reverse_iterator<InputIt1>& lhs, const reverse_iterator<InputIt2>& rhs);
- 두 반복자
lhs
,rhs
의 다름 여부를 판단하는 부등호 연산자 오버로드
operator<
bool operator<(const reverse_iterator<InputIt1>& lhs, const reverse_iterator<InputIt2>& rhs);
- 두 반복자
lhs
,rhs
의 위치를 비교하는 부등호 연산자 오버로드lhs
가 더 클 경우 참이 된다 (역방향 반복자이므로)
operator<=
bool operator<=(const reverse_iterator<InputIt1>& lhs, const reverse_iterator<InputIt2>& rhs);
- 두 반복자
lhs
,rhs
의 위치를 비교하는 부등호 연산자 오버로드lhs
가 더 크거나 같을 경우 참이 된다 (역방향 반복자이므로)
operator>
bool operator>(const reverse_iterator<InputIt1>& lhs, const reverse_iterator<InputIt2>& rhs);
- 두 반복자
lhs
,rhs
의 위치를 비교하는 부등호 연산자 오버로드lhs
가 더 작을 경우 참이 된다 (역방향 반복자이므로)
operator>=
bool operator>=(const reverse_iterator<InputIt1>& lhs, const reverse_iterator<InputIt2>& rhs);
- 두 반복자
lhs
,rhs
의 위치를 비교하는 부등호 연산자 오버로드lhs
가 더 작거나 같을 경우 참이 된다 (역방향 반복자이므로)
참고 자료
https://en.cppreference.com/w/cpp/container/vector
cppreference
를 보십시오 휴먼
'42 > 42s Cursus' 카테고리의 다른 글
[Rank 5] ft_containers - std::vector (4) | 2023.02.04 |
---|---|
[Rank 5] ft_containers - Allocator (0) | 2023.01.19 |
[Rank 5] ft_containers - explicit 키워드 (0) | 2023.01.13 |
[Rank 5] ft_containers - std::iterator_traits (0) | 2023.01.11 |
[Rank 5] ft_irc - 만들어야 하는 명령어 정리 (3) | 2023.01.07 |
Comments