본문 바로가기
C++

C++ iterator

by 안선생 2022. 9. 2.

iterator(반복자)

컨테이너에 저장되있는 원소들을 공통적인 방법으로 하나씩 접근할 수 있게 해준다. 

즉 포인터라고 생각하면 편함 begin을 하면 첫번째 주소를 가르켜준다 호출할 떄도 *을 붙여야한다.

 

 

반복자 직접 구현해보기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#pragma once
#include <assert.h>
#include <iostream>
using namespace std;
template<typename T>
class CArr
{
private:
    T* pint;
    int count;
    int maxcount;
public:
    void PushBack(const T& Data); // 
    void resize(int ResizeCount);
    void Sort();
    T* data() { return pint; }
    int size() { return count; }
    int capacity() { return maxcount; }
    
    T& operator[] (int idx); // operator를 써줘야함
    class iterator;
    iterator begin();
    iterator end();
 
public:
    CArr();
    ~CArr();
    //클레스 안에 클레스 = 이너 클래스
    // inner 클래스를 포함하고있는 클래스의 private 접근 가능
    class iterator // 우리가 만든 가변배엘에 데이터들을 가르키게 할 수 있게 만듦
    {
    private:
        //백터가 넘쳐서 새로 재활당 될경우 백터자체에 주소를 알아야함
        CArr* cpint; // iterator 가 가리킬 데이터를 관리하는 가변배열 주소
        T*  ipint; //데이터의 시작주소
        int index; //몇번째를 가르키고 있는지 idex
 
    public:
        T& operator *()
        {
            //iterator가 알고있는 주소와, 가변배열이 알고 있는 주소가 달라진 경우(공간 확장으로 주소가 달라진 경우)
            // iterator가 end iterator 인 경우
            if (cpint->pint != ipint || index == -1)
            {
                assert(false);
            }
            return ipint[index];
        }
 
        //전위
        iterator& operator ++()
        {
            // 1. iterator 가 마지막 데이터를 가리키고 있는 경우
            // --> end iterator 가 된다.
            if (cpint->count -1 == index)
            {
                index = -1;
            }
            else
            {
                index++;
            }
            // 2. end iterator 인 경우
            // 3. iterator가 알고있는 주소와, 가변배열이 알고 있는 주소가 달라진 경우(공간 확장으로 주소가 달라진 경우)
            if (cpint->pint != ipint || index == -1)
            {
                assert(false);
            }
 
            ++index;
            return *this;
        }
 
 
        // ++ 후위
        iterator operator ++(int)// &복사본을 호출하면 이미 실행되기 때문 int는 아무 의미 없음
        {
            
            iterator copyiter = *this//this는 호출한 객체
 
            ++(*this);
 
            return copyiter;
        }
 
        iterator& operator --()
        {
 
            return *this;
        }
 
        // 비교ㅕ연산자 ==, !=
        bool operator == (const iterator& other)
        {
            if (ipint == other.ipint && index == other.index)
            {
                return true;
            }
            return false;
        }
 
        bool operator != (const iterator& other)
        {
            return !(*this == other); // 위에 == 함수 반대로 한것
        }
    public:
        iterator()
            :cpint(nullptr)
            ,ipint(nullptr)
            ,index(-1)
        {
        }
        iterator(CArr* cpint,T* ipint, int idex)
            :cpint(pint)
            ,ipint(ipint)
            ,idex(idex)
        {
 
        }
        ~iterator()        
        {
            delete cpint;
            delete ipint;
            index = -1;
        }
    };
};
 
template<typename T>
CArr<T>::CArr()  // T자료형안에 선언되있는 클래스 <T>를 지정해줘야함
// 클래스 선언 범위 밖에서 지정했기때문에 CArr클래에 지정되어있는 생성자라는 뜻
    //이니셜라이저로 초기화
    : pint(nullptr)
    , count(0)
    , maxcount(2)
{
    pint = new T[2]; // new 새로운 C++동적활당 malloc 이랑 같음 
    // int2개만큼 할당
 
}
template<typename T>
CArr<T>::~CArr()
{
    //delete 동적할당 해제 free랑 같음
    for (int i = 0; i < count; i++)
    {
        cout << pint[i] << endl;
    }
    delete[] pint; // 위에 인트 자료형을 여러게 선언했기 떄문에 []붙여줌 하나만 선언할시 []안붙여도 된다.
    count = 0;
    maxcount = 0;
 
}
template<typename T>
void CArr<T>::PushBack(const T& Data)
{
    if (this->maxcount <= this->count)
    {
        resize(maxcount * 2);
    }
 
    pint[this->count++= Data;
}
template<typename T>
void CArr<T>::resize(int ResizeCount)
{
    //현재 최대 수용량 보다 더 적은 수치로 확장하려는 경우
    if (maxcount >= ResizeCount)
    {
        assert(nullptr);
    }
 
    // 1. 리사이즈 시킬 개수만큼 동적할당 한다.
    T* pnew = new T[ResizeCount];
 
    // 2 기존 공간에 있던 데이터들을 새로 할당한 공간으로 복사시킨다.
    for (int i = 0; i < this->count; i++)
    {
        pnew[i] = this->pint[i];
    }
 
    // 3. 기존 공간은 메모리 해제
    delete[] pint;
 
    // 4. 배열이 새로 할당된 공간을 가리키게 한다.
    this->pint = pnew;
 
    //5 . maxcoyunt 변경점 적용
    this->maxcount = ResizeCount;
 
}
template<typename T>
void CArr<T>::Sort()
{
    if (count < 1)
    {
        return;
    }
 
    while (1)
    {
        
        bool finsih = true;
        for (int i = 0; i < count - 1; i++) {
            if (pint[i] > pint[i + 1])
            {
                int re = pint[i];
                pint[i] = pint[i + 1];
                pint[i + 1= re;
                finsih = false;
            }
        }
        if (finsih == true)
        {
            break;
        }
    }
}
 
 
 
template<typename T>
T& CArr<T>::operator[](int idx)
{
    return pint[idx];
}
 
template<typename T>
//typename적어준 이유는 이너클래스인 경우 반환내용이 iterator인것을 알려주기위해
typename CArr<T>::iterator CArr<T>::begin()
{
    if (count == 0)
    {
        return iterator(thisthis->pint, -1); //데이터가 없는 경우, begin() == end()
    }
    // 시작을 가리키는 iterator 를 만들어서 반환해줌
    //iterator iter(this->pint, 0);
    return iterator(thisthis->pint, 0); //임시객체라고 해서 변수명을 안짖고 바로 만들어줌
}
 
template<typename T>
typename CArr<T>::iterator CArr<T>::end()
{
    
    return iterator(thisthis->pint, -1); //임시객체라고 해서 변수명을 안짖고 바로 만들어줌
}
 
cs

 

출처 : https://www.youtube.com/c/AssortRockGameAcademy

'C++' 카테고리의 다른 글

C++ list iterator  (1) 2022.09.13
C++ erase  (0) 2022.09.05
C++ STL(vector,list)  (0) 2022.08.31
C++ namespace , 입출력 구현  (0) 2022.08.31
C++ 클래스 템플릿  (2) 2022.08.27