Анимация
JavaScript
|
Главная Библионтека Итераторы Итератором называется объект, предназначенный для перебора элементов контейнера STL (всех или некоторого подмножества). Итератор представляет некоторую позицию в контейнере. Ниже перечислены основные операторы, работу с которыми поддерживает итератор, О * - получение элемента в текущей позиции итератора. Если элемент состоит из отдельных членов, для обращения к ним неносредственно через итератор используется оператор О ++ - перемещение итератора к следующему элементу. Многие итераторы также поддерживают перемещение в обратном направлении, для чего используется оператор ~, О == и != - проверка совпадений позиций, представленных двумя итераторами. О = - присваивание итератора (позиции элемента, на которую он ссылается). Этот набор операторов в точности соответствует интерфейсу обычных указателей С и С++ при переборе элементов массива. Различие заключается в том, что итераторы могут быть умньши указателями, обеспечивающими перебор в более сложных контейнерных структурах данных. Внутреннее поведение итератора зависит от структуры данных, в которой осуществляется перебор. Таким образом, каждая разновидность контейнеров обладает собственным итератором. В каждом контейнерном классе тип итератора определяется в виде вложенного класса. В результате все итераторы обладают одинаковым интерфейсом, но имеют разные типы. В итоге мы приходим к концепции унифицированного программирования: операции выполняются с одинаковым интерфейсом, но с разными типами, что позволяет использовать шаблоны для определения унифицированных операций, работающих с произвольными типами, которые поддерживают заданный интерфейс. Во всех контейнерных классах поддерживаются базовые функции, применяемые для перебора элементов при помощи итераторов. Ниже перечислены важнейшие из этих функций. О begin() - возвращает итератор, установленный в начало последовательности элементов контейнера. Началом считается позиция первого элемента (если on есть). О end() - возвращает итератор, установленный в конец последовательности элементов контейнера. Концом считается позиция за последним элементом. Итак, функции beginO и end() определяют полуоткрытый интервал, который содержит первый элемент, но выходит за пределы последнего элемента (рис. 5.3). Полуоткрытый интервал обладает двумя достоинствами: О появляется простое условие завершения перебора в контейнере: цикл продолжается до тех пор, пока не будет достигнута позиция end(); О предотвращается специальная обработка пустых интервалов, поскольку в пустом интервале begin() совпадает с end(). На некоторых старых платформах итераторы еще не поддерживают оператор ->. beginO end О Рис. 5.3. Функции beginQ и endQ Следующий пример демонстрирует применение итераторов. В нем выводятся значения всех элементов списка (усовершенствованная версия примера со списками, приведенного на с. 92). stl/list2,cpp include <1ostreafn> include <l1st> using namespace std: int mainC) list<char> coll: Список с символьными элементами Присоединение элементов от а до z for (char с=а: c<=z: ++с) ( coll,push backCc): /* Вывод содержимого списка * - перебор всех элементов. */ list<char>::const iterator pos: for epos = coll ,begin(): pos -coll.endO: ++pos) { cout « *pos « : cout « endl: После того как список создан и заполнен символами от «а» до «z », все элементы выводятся в цикле for: list<char>::const 1terator pos; for epos = coll.beginC): pos != coll.endC): ++pos) { cout « *pos « ; Итератор pos объявляется непосредственно перед началом цикла. В объявлении выбирается тип итератора для обращения к элементам контейнерного класса без возможности модификации: list<char>::const iterator pos: В каждом контейнере определены два типа итераторов: О контейнер:Aterator - используется для перебора элементов в режиме чтения/записи; О KonmeUHepy.constJteratQT - используется для перебора элементов в режиме чтения. Скажем, в классе list эти определения выглядят примерно так: namespace std { template <cla5s Т> class list ( public: typedef ... Iterator: typedef ... const iterator: Конкретный тип итераторов iterator и constjterator зависит от реализации. В теле цикла for итератор pos инициализируется позицией первого элемента: pos = coll.begInC); Цикл продолжается до тех пор, пока ров не выйдет за пределы интервала контейнерных элементов: pos != coll .endO : В этом условии итератор pos сравнивается с конечным итератором. Оператор ++POS в заголовке цикла перемещает итератор pos к следующему элементу. В итоге итератор pos перебирает все элементы, начиная с первого, пока не дойдет до конца (рис. 5.4). Если контейнер не содержит ни одного элемента, тело цикла не выполняется, потому что значение coll.begin() будет равным значению colI.endQ. Рис. 5.4. Итератор pos при переборе элементов списка В теле цикла текущий элемент представляется выражением *pos. Модификация текущего элемента невозможна, потому что итератор был объявлен с типом const iterator, а значит, с точки зрения итератора элементы являются константными. Но если объявить неконстантный итератор дляперебора неконстантных элементов, значения можно будет изменить. Пример: Приведение всех символов в списке к верхнему регистру list<char>::iterator pos: 0 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 |