내돈내고 내가 공부한것을 올리며, 중요한 단원은 저 자신도 곱씹어 볼겸 가겹게 포스팅 하겠습니다.
1) 10장. 반복자
반복자는 컨테이너의 원소를 순회하고 접근하는 일반화된 방법을 제공한다.
반복자의 종류
- 입력 반복자: 전방향 읽기(istream)
- 출력 반복자: 전방향 쓰기(ostream)
- 순방향 반복자: 전방향 읽기, 쓰기
- 양방향 반복자: 양방향 읽기, 쓰기
- 임의 접근 반복자: 랜덤 읽기, 쓰기
X::iterator와 X::const_iterator
아 처음볼때 X가 뭐지?? 이런생각이 들 수 있는데 컨테이너를 표시한거다. vector<int>::iterator에서 vector<int>가 X이다.
- X::iterator: 정방향 반복자의 내장 형식. 반복자가 가리키는 원소 읽기, 쓰기 가능
- X::const_iterator: 정방향 반복자의 내장 형식, 반복자가 가리키는 원소의 읽기 가능. 가리키는 원소가 const 객체이다.
다음 코드를 통하여 확인해 보자.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
cout << "iterator : ";
vector<int>::iterator iter = v.begin();
for (; iter != v.end(); iter++)
cout << *iter << " ";
cout << endl;
cout << "const iterator : ";
vector<int>::const_iterator citer = v.begin();
for (; citer != v.end(); citer++)
cout << *citer << " ";
cout << endl;
*iter = 100;
// *citer = 100; 쓰기 불가
return 0;
}
결과는 생각한대로 나오며 const_iterator의 경우 읽기는 가능하지만 쓰기가 불가능 하다.
즉 const_iterator와 iterator의 차이는 값을 변경할수 있냐 없냐의 차이다.
다음으로는
vector<int>::iterator iter = v.begin();
const vector<int>::iterator iter = v.begin();
이 둘간의 차이를 알아보자. 사실 매우 간단한데, const가 없는 방식은 가리키는 대상의 위치가 변경이 가능하지만, const가 있는 경우에는 가리키는 대상의 위치가 변경이 불가능 하다. 반복자 자체가 const 객체인 것 이다.
X::reverse_iterator와 X::const_reverse_iterator
- X::reverse_iterator: 역방향 반복자의 내장 형식. 반복자가 가리키는 원소 읽기, 쓰기 가능
- X::const_reverse_iterator: 역방향 반복자의 내장 형식. 반복자가 가리키는 원소 읽기 가능
삽입 반복자
삽입 반복자는 순차열에 원소를 삽입할 수 있게 반복자를 변환하는 반복자 어댑터 이다. 이를 이용하면 알고리즘을 삽입 모드로 동작시킬 수 있다.
- inserter(): inserter_iterator 객체를 생성하여 컨테이너의 insert() 멤버 함수를 호출해 삽입 모드로 동작합니다.
- back_inserter(): back_inserter_iterator 객체를 생성하여 컨테이너의 push_back() 멤버 함수를 호출해 뒤쪽에 추가하도록 동작.
- front_inserter(): front_inserter_iterator 객체를 생성하여 컨테이너의 push_front() 멤버 함수를 호출해 앞쪽에 추가하도록 동작.
다음 코드를 통하여 inserter()에 대하여 알아보자.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
vector<int> v2;
copy(v1.begin(), v1.end(), inserter<vector<int>>(v2, v2.begin()));
cout << "v1 > ";
for (vector<int>::iterator iter = v1.begin(); iter != v1.end(); iter++)
cout << *iter << " ";
cout << endl;
cout << "v2 > ";
for (vector<int>::iterator iter = v2.begin(); iter != v2.end(); iter++)
cout << *iter << " ";
cout << endl;
return 0;
}
결과로는 다음과 같다.
inserter<vector<int>>(v2, v2.begin()) 은 v2.begin() 반복자를 v2의 insert() 멤버 함수를 호출하는 삽입 반복자로 변환합니다.
또한 copy알고리즘은 덮어쓰기가 기본 default동작으로 만약 inserter() 어댑터를 사용하지 않는다면 v2의 사이즈가 0으로 실행 오류가 난다.
입/출력 스트립 반복자
스트림과 연결된 반복자로 알고리즘이 스트림에 읽고 쓸 수 있도록 하는 반복자 어댑터 이다.
- istream_iterator<T>: 입력 스트림과 연결된 반복자로 T 형식의 값을 스트림에서 읽을 수 있습니다.
- ostream_iterator<T>: 출력 스트림과 연결된 반복자로 T 형식의 값을 스트림에 쓸 수 있습니다.
반복자 특성과 보조 함수
반복자는 위에서 말했듯 5가지 반복자(입력, 출력, 순방향, 양방향, 임의 접근)로 분류된다.
이들은 각각 자신만의 특징을 갖는데, 이 특징을 저장하는 템플릿 클래스를 iterator traits라고 한다. 또한, 반복자를 지원하는 두 함수 advance()와 distance() 함수로 임의 접근 반복자 만이 갖고있는 연산을 다른 반복자에서도 사용 가능하도록 돕는다.
- advance(p, n): p 반복자를 p += n의 위치로 이동시킨다.
- n = distance(p1, p2): n은 p2 - p1 입니다.
다음 코드를 통하여 확인해 보자.
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
list<int> v2;
v2.push_back(1);
v2.push_back(2);
v2.push_back(3);
vector<int>::iterator vecIter(v1.begin());
list<int>::iterator liIter(v2.begin());
vecIter += 2;
cout << "v1 += 2 : " << *vecIter << endl;
advance(liIter, 2);
cout << "v2 += 2 : " << *liIter << endl;
return 0;
}
결과는 다음과 같다.
vector같은 임의 접근 반복자는 바로 +=2 가 가능하지만, list같은 양방향 접근 반복자는 advance를 사용해줘야 한다.
2) 나의 현황
자료구조 책을 정하고 바로 주문했다. 천인국 교수님의 C++로 쉽게 풀어쓴 자료구조 를 구매하였다.
사실 교보문고 평점은 약간 알바가 껴있는 느낌을 받은적이 있어 여러 타회사의 책 리뷰를 봤는데 평이 좋지 않았다.
대부분 하는말이 코드가 이상하다는 것 이다. 하지만 대안으로 읽을 책이 명확히 없었다.
이석호교수님이 번역해주신 C++ 자료구조론 이라는 책이 있지만, 너무 이론에 치중해 있는 느낌을 받아 읽고 싶은 생각이 안드는 책이였다.
또 다른 C++로 구현하는 자료구조와 알고리즘 이라는 책은 해외 아마존 평가를 봤는대 평이 별로 좋지 못했다. 국내 평은 좋긴 한것같은데 도서관에서 직접 보니 코드가 부족한 느낌이였다.
그래서 오늘 학교 도서관에 가서 몇가지 자료구조 책들을 펴놓고 정독하였다. 그결과 생각보다 C++로 쉽게 풀어쓴 자료구조 책이 잘 읽혔다. 도서관에서 3장 list까지 다 읽고 왔다. template을 사용한 제네릭 class를 설계하지 않는다는 점이 걸렸지만, 뭐 이건 열혈 자료구조도 대부분이 int형 위주로 설명하니 상관 없을거라 생각했다.
설령 책이 부족하더라도 읽는 사람의 마음가짐이 중요하다 느낀적이 많다. 책이 이상하다 싫다 생각하는 순간 계속 책의 오류만 눈에 보이기 마련이다. 이왕 돈들여 산 아까운 책 깊이 파보자. 부족한 부분은 내가 구글링 하면서 코드를 새로 짜보자. 이를 통해 더욱 배움의 길로 나아갈 수 있을것 이다.
이글의 모든 사진과 내용의 출처는 공동환 님께 있습니다.
'CS > C++' 카테고리의 다른 글
뇌를 자극하는 C++ STL : 12장. string 컨테이너 (0) | 2022.01.18 |
---|---|
뇌를 자극하는 C++ STL : 11장. 컨테이너 어댑터 (0) | 2022.01.18 |
뇌를 자극하는 C++ STL : 9장. 함수 객체 (0) | 2022.01.18 |
뇌를 자극하는 C++ STL : 8장. 알고리즘 (0) | 2022.01.18 |
뇌를 자극하는 C++ STL : 7장. 연관 컨테이너 (0) | 2022.01.18 |
댓글