헤더파일
반복자 본문
template<typename T>
void f(T a, T b)
{
auto temp = *a;
*a = *b;
*b = temp;
}
int main()
{
vector<int> v{ 1,2,3,4,5 };
//f는 두 반복자가 가리키는 값을 교환하는 함수
f(v.begin(), v.end() - 1);
for (auto& data : v)
{
cout << data << endl;
}
return 0;
}
여기서 반복자의 크기는 4바이트 이므로 레퍼런스 붙이는 건 의미가 없습니다.
알아야할껀 템플릿 함수는 컴파일 할 때 코드를 찍어내므로 빨간줄이 안 그어집니다. 변수형을 지정안하고 temp = *a 이렇게 써도 코드 작성중에는 문제가 있는지 안 알려줍니다.
하지만 temp의 자료형은 auto를 안 쓰면 어떻게 알 수 있을까요?
반복자는 자료구조와 알고리즘을 이어줄려는 목적으로 쓴다. 알고리즘 입장에서는 자료구조가 어떻게 메오리가 구성되어 있는지 알 필요없기 때문입니다. find함수 입장에서는 주어진 범위를 돌아다니기만 하면됩니다. find함수거나 다른 함수인데 전달되는 반복자가 어떤 자료구조에서 나온건지 표시 할 수 있다면 더 좋게 만들 수 있습니다.
모든 STL반복자는 특성을 정의해야 합니다.
1.어떤 형태의 반복자니?
2.포인터로 바꾸면 어떤 포인터니?
3.레퍼런스로 바꾸면 어떤 타입이니?
4.너가 가리키고 있는 타입은 뭐니?
5.너랑 다른 반복자와 거리를 재면 무슨 값이니?
그래서 STL은 iterator_traits라는 클래스를 제공하는데
typename iterator_traits<T>::value_type temp = *a;
처럼 써서 자료형을 얻어올 수도 있고 여러 정보를 얻어올 수 있습니다.
typename iterator_traits<T>::iterator_category c;
cout << typeid(c).name() << endl;
벡터의 반복자를 넘겨준다면 이렇게 카테고리를 줍니다. -> struct std::random_access_iterator_tag
포인터를 넘겨도 -> struct std::random_access_iterator_tag
리스트를 넘기면 -> struct std::bidirectional_iterator_tag
반복자를 이용해서 컨테이너의 크기를 얻어 봅시다.
메모리가 연속적인 random_access라면
int MyDist(Iter begin, Iter end)
{
return end - begin;
}
-연산자로 구할 수 있습니다.
하지만 list같은 메모리 구조라면 이런 형태로 구할 수 없습니다.
template<typename Iter>
int MyDist(Iter begin, Iter end)
{
typename iterator_traits<Iter>::iterator_category c;
if (string(typeid(c).name()) == "struct std::random_access_iterator_tag")
{
cout << "랜덤 액세스의 반복자다!" << endl;
return end - begin;
}
int cnt = 0;
while (begin != end)
{
cnt++;
begin++;
}
return cnt;
}
STL 클래스인 String 클래스를 직접 작성해보고 반복자 구현하기!
또 표준 반복자라면 iterator_traits<반복자>::iterator_category변수를 가져야 합니다.
class myRevIterator : public iterator<random_access_iterator_tag, char> {
char* p;
public:
myRevIterator(char* p) : p{ p } {
}
char& operator*() {
char c = *(p - 1);
return c;
}
myRevIterator operator++() {
--p;
return *this;
}
bool operator!=(const myRevIterator& other)const {
return p != other.p;
}
};
class myIterator : public iterator<random_access_iterator_tag, char> {
char* p;
public:
myIterator(char* p) : p{ p } {
}
char& operator*() {
return *p;
}
bool operator==(const myIterator& other) {
return p == other.p;
}
bool operator!=(const myIterator& other) {
return p != other.p;
}
void operator=(const myIterator& other) {
p = other.p;
}
myIterator& operator++() {
++p;
return *this;
}
myIterator operator++(int) {
myIterator temp(p);
++p;
return temp;
}
//랜덤 엑세스 반복자가 지원하는 연산들
int operator-(const myIterator& rhs) const { return p - rhs.p; }
myIterator operator+(int n) const {
myIterator temp(p);
temp.p += n;
return temp;
}
bool operator<(const myIterator& rhs)const {
return *p < *rhs.p;
}
myIterator operator-(int n) {
myIterator temp(p);
temp.p -= n;
return temp;
}
myIterator& operator--() {
--p;
return *this;
}
myIterator operator--(int) {
myIterator temp(p);
--p;
return temp;
}
};
class myString {
char* p;
int len;
public:
using iterator = myIterator;
myString(const char* s) {
len = strlen(s);
p = new char[len + 1];
strcpy(p, s);
}
myString(const myString& other)
{
len = other.len;
p = new char[len + 1];
strcpy(p, other.p);
}
myString& operator=(const myString& other)
{
len = other.len;
p = new char[len + 1];
strcpy(p, other.p);
delete[] p;
}
myString operator+(const char*s)
{
int num = len + strlen(s);
char* q = new char[num + 1];
strcpy(q, p);
strcat(q, s);
myString m(q);
delete[] q;
return m;
}
~myString()
{
delete[] p;
}
myIterator begin() {
return myIterator(p);
}
myIterator end() {
return myIterator(p + len);
}
myRevIterator rbegin() {
return myRevIterator(p + len);
}
myRevIterator rend() {
return myRevIterator(p);
}
friend ostream& operator<<(ostream&, const myString&);
};
ostream& operator<<(ostream& os, const myString& s)
{
os << s.p;
return os;
}
int main()
{
myString s{ "Hello,STL!" };
for (auto p = s.rbegin(); p != s.rend(); ++p)
cout << *p << ' ';
cout << endl;
//sort(s.begin(),s.end());
//for (auto d : s) {
// cout << d ;
//}
//cout << endl;
}
'C++' 카테고리의 다른 글
문자열 함수 (0) | 2018.06.11 |
---|---|
알고리즘 함수 (0) | 2018.05.31 |
Map을 이용한 파일입출력 (0) | 2018.05.14 |
연관 컨테이너 (0) | 2018.04.30 |
노말분포 & 시퀀스 컨테이너 (0) | 2018.04.16 |