스토리텔링 개발자

[Effective STL] 27. const_iterator를 iterator로 바꾸기 본문

개발/Effective STL

[Effective STL] 27. const_iterator를 iterator로 바꾸기

김디트 2024. 12. 12. 10:50
728x90

항목 27. const_iterator를 iterator로 바꾸는 데에는 distance와 advance를 사용하자

 

 

 

const_iterator를 iterator로 캐스팅?
  • const_iterator는 암묵적 변환이 일어나지 않으므로 직접 바꿔주어야 한다.
  • 그렇다면 캐스팅(casting)을 쓰면 될까?
using IntDeque = deque<int>;
using Iter = IntDeque::iterator;
using ConstIter = IntDeque::const_iterator;

IntDeque d;
ConstIter ci;
...
Iter i(ci); // 에러 발생. 암묵적 변환은 불가능하다.
Iter i2(const_cast<Iter>(ci); // 여전히 에러. 캐스팅이 불가능하다.
  • const_iterator와 iterator는 전혀 관계없는 다른 클래스이다.
    • 그렇기에 컴파일러가 변환을 거부하는 것이다.
  • vector나 string에서는 구현에 따라 가능할 수도 있다.
    • 반복자를 포인터로 구현하여 typedef 하는 경우가 왕왕 있기 때문이다.
    • const T*를 T*로 캐스팅 하는 것은 당연히 성공이다.
    • 하지만... reverse_iterator와 const_reverse_iterator는 또 진짜 클래스로 구현되어 있다. 이 경우는 캐스팅이 또 불가능해진다.
    • 이런 방법은 물론 컴파일러에 따라 가능한 것이므로 이식성에 문제가 생긴다.

 

 

 

advence, distance 함수
using IntDeque = deque<int>;
using Iter = IntDeque::iterator;
using ConstIter = IntDeque::const_iterator;

IntDeque d;
ConstIter ci;
...
Iter i(d.begin()); // 우선 d의 요소를 가리키도록 한다.
advance(i, distance(i, ci)); // ci가 있는 곳으로 i를 옮긴다.
  • advance 함수
    • 어떤 반복자를 지정한 거리만큼 이동시킨다.
  • distance 함수
    • 같은 컨테이너를 가리키는 두 반복자 사이의 거리를 알려준다.
  • 허나, 지금 코드로는 컴파일이 되지 않는다.
    • 넘겨진 두 매개변수의 타입이 달라서, 반복자 타입을 명확히 추론해내지 못한다.
template<typename InputIterator>
typename iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last);
// 다음 선언문을 보면 알 수 있듯이,
// distance는 InputIterator/를 통해 타입을 추측해야 한다.

advance(i, distance(i, ci));
// i의 타입은 deque<int>::iterator
// ci의 타입은 deque<int>::const_iterator
// 두 타입이 다르므로 distance는 타입을 명확히 추론할 수 없다.

// 다음과 같이 바꿔준다.
advance(i, distance<ConstIter>(i, ci));
// iterator -> const_iterator는 암시적 변환이 가능하기 때문이다.

참고를 위한 iterator들의 관계표

 

 

 

효율
  • 반복자의 특성만큼 효율도 다르다.
    • 즉, distance로 구한 거리 이동에 필요한 만큼 자원을 소모한다.
  • 임의 접근 반복자의 경우 상수 시간에 동작이 완료되지만..
  • 양방향 반복자의 경우 선형 시간에 동작이 완료된다.
728x90
Comments