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(this, this->pint, -1); //데이터가 없는 경우, begin() == end() } // 시작을 가리키는 iterator 를 만들어서 반환해줌 //iterator iter(this->pint, 0); return iterator(this, this->pint, 0); //임시객체라고 해서 변수명을 안짖고 바로 만들어줌 } template<typename T> typename CArr<T>::iterator CArr<T>::end() { return iterator(this, this->pint, -1); //임시객체라고 해서 변수명을 안짖고 바로 만들어줌 } | cs |
'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 |