스토리텔링 개발자

[Effective STL] 28. 반복자 base() 유의점 본문

개발/Effective STL

[Effective STL] 28. 반복자 base() 유의점

김디트 2024. 12. 13. 10:35
728x90

항목 28. reverse_iterator에 대응되는 베이스 반복자(base iterator)를 사용하는 방법을 정확하게 이해하자

 

 

 

대응되는 반복자 사용 예
vector<int> v;
v.reserve(5);

for(int i = 1 ; i <= 5 ; ++i)
{
    v.push_back(i);
}

vector<int>::reverse_iterator ri = find(v.rbegin(), v.rend(), 3); // ri는 3을 가리킨다.
vector<int>::iterator i(ri.base()); // i를 ri와 같은 곳을 가리키게 한다.
  • 이 코드 처리 후의 상황은 아래와 같다.

ri와 i가 같은 위치를 가리키지 않는다?

  • 왜 그럴까?
  • reverse_iterator로는 삽입이나 삭제를 할 수 없다.(항목 26 참조)
  • 만약 ri로 99를 삽입하여 아래처럼 만들고 싶다고 하면..

  • reverse_iterator를 삽입 함수에 사용할 수 없으므로 ri 대신 i를 써야 할 것이다.
    • 즉, ri를 사용하여 삽입하고자 하는 위치를 i가 가리키고 있기 때문에!
    • i는 4를 가리키고 있는 것이다.
  • 하지만, 만약 ri로 현재 가리키는 요소 위치를 삭제하고 싶다고 하면..
    • i의 앞 요소를 삭제해야 한다.

 

 

 

정리
  1. reverse_iterator인 ri로 지정된 위치에 대한 요소를 삽입하려면 ri.base()를 사용한다.
    • 요소 삽입이 목적이라면 ri와 ri.base()는 동등하다.
    • ri.base()는 ri에 정확하게 대응되는 반복자이다.
  2. reverse_iterator인 ri로 지정된 위치에 대한 요소를 삭제하려면 ri.base() - 1을 사용한다.
    • 요소 삭제가 목적이라면 ri와 ri.base()는 동등하지 않다.
    • ri.base()는 ri에 대응되는 반복자가 아니다.

 

 

 

삭제 시 유의점
vector<int> v;

...

vector<int>::reverse_iterator ri = find(v.rbegin(), v.rend(), 3);

v.erase(--ri.base()); // ri.base()의 앞 요소를 삭제한다. 하지만.. 일반적으로는 컴파일 에러
  • C, C++의 규정에 의하면, 함수에서 반환된 포인터는 수정(modify)할 수 없기 때문이다.
    • 그러므로 vector, string의 iterator가 포인터로 구현된 STL 플랫폼에서 --ri.base()라는 표현식은 컴파일 될 수 없다.
  • 이식성 문제를 고려하면 base 반환값을 수정하지 않도록 하는 것이 좋다.
v.erase((++ri).base()); // reverse_iterator를 수정하여 base()를 호출하여 해결

 

728x90
Comments