-
[C++] C++ iterator, 반복자 - 1쾌락없는 책임 (공부)/C++ 짜잘이 2022. 8. 13. 15:01반응형
개요
평소 iterator를 사용하지 않고 살아오다가 반복자에 대한 부분이 많이 부족한거 같아 이참에 한번 정리를 해보기로 했습니다. 보면서 아주 중구난방의 이야기들이 오가니 참고용 자료가 되지는 못할 것 같습니다.
C++에서 iterator 사용
기존 배열, vector의 경우 인덱스를 통한 랜덤 접근이 가능하기에 반복자에 대한 필요성이 강조되지 않습니다. 하지만 set, map 등의 자료구조는 구조가 vector와 다르죠. 때문에 이것들을 탐색하기 위해서 반복자가 사용되게 됩니다.
일단 가장 쉬운 예시인 std::vector에 대해서 보겠습니다. 일단 begin(), end() 함수가 있는 만큼 vector는 반복자를 제공해 줍니다.
일단 vector 에서는 4개의 iterator를 두고 있습니다. 여기서 const는 내부를 변경할 수 없게 해주는 반복자이고 reverse의 경우 역방향 반복자가 됩니다.
이런식으로 사용하면 vector의 전부를 볼 수 있게 됩니다. vector는 인덱스가 있기에 사실 이런 동작을 굳이 하는게 이해가 잘 안되지만 다른 자료구조를 보면 사용 이유를 알 수 있게 됩니다.
#include <iostream> #include <unordered_map> using namespace std; int main(){ unordered_map<string, int> map; map["me"] = 1; map["you"] = 2; //! index로 불가능 // for(int i = 0; i < map.size(); i++){ // cout << map[i] << " " // } unordered_map<string, int>::const_iterator itr; for(itr = map.begin(); itr != map.end(); itr++) { cout << itr->first << " / " << itr->second << '\n'; } }
이런식으로 해시맵을 탐색할 수 있게 됩니다. 추가적으로 최신 버전에서는 아래처럼 간단하게 작성할 수 있습니다.
for(auto node : map) { cout << node.first << " / " << node.second << '\n'; }
위처럼 간단하게 변경된 것은 범위 기반 반복문(Range-based for loop)라고 합니다.
추가적으로 C++ 17버전에서는 아래와 같은 문법이 된다고 합니다.
for(auto [key, value] : map) { cout << key << " / " << value << '\n'; }
여기서 unordered_map의 예시를 보았을 때 반복자의 사용 이유는 인덱스 증가를 통해 접근하기 어려운 컨테이너를 순회 탐색하기 위함입니다.
reverse iterator - 역방향 반복자
일단 unordered_map에는 역방향 반복자가 없습니다. 대신 vector에서는 역방향 반복자가 있습니다. 그러면 이놈들의 정체는 뭘까요? 일단 vector에서 반복자를 위한 begin(), end()와 역방향 반복자를 위한 rbegin(), rend() 의 위치를 봐야 합니다.
begin() end() data data data data rend() rbegin() 대략 요런 모습이라고 생각하시면 됩니다.
#include <iostream> #include <vector> using namespace std; int main(){ using v = vector<int>; v vec = { 1, 2, 3, 4, 5 }; v::iterator itr; v::reverse_iterator rItr; for(itr = vec.begin(); itr != vec.end(); itr++){ cout << *itr << " "; } cout << endl; for(rItr = vec.rbegin(); rItr != vec.rend(); rItr++){ cout << *rItr << " "; } }
코드로 역방향 반복자를 사용하면 이런 모습이 됩니다. 이런식으로 역방향으로 탐색을 할 수 있게 됩니다. 그리고 만일 역방향 반복자를 순방향으로 바꾸기 위해서는 .base()를 해주면 됩니다.
벡터와 리스트는 어떻게 다를까
벡터의 반복자는 itr + i가 됩니다. 다만 list의 itr은 증감연산자만 사용이 가능합니다. 이는 벡터와 다르게 임의 접근 지정이 되지 않아서 생기는 일이라 볼 수 있습니다. 리스트의 반복자는 양방향 반복자이고 벡터의 반복자는 이를 상속받은 임의접근 반복자라 차이가 생길 수 있는 것이죠.
그리고 구조상 벡터는 erase를 하면 반복자들이 무효화 되어 추가 조치를 취해줘야 하지만 리스트의 경우 그런거 없이 계속해서 사용할 수 있다는 장점이 있습니다.
반응형'쾌락없는 책임 (공부) > C++ 짜잘이' 카테고리의 다른 글
[C++] vector, deque 의 차이 - 메모리는 어떻게 관리할까? (0) 2022.08.14 [C++] C++ sort는 어떤 알고리즘을 사용할까 (0) 2022.08.13 [C++] shared_ptr 은 어떻게 동작하게 될까? (0) 2022.08.09 [C++] C++의 move semantics (의미론적 이동?) (0) 2022.08.07 [C++] C++ 로 중복 없는 랜덤 변수 만드는 방법 - 1 (0) 2022.08.05