|
186 / 186 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
|
|
Как более менее правильно написать итератор(не STL).17.09.2011, 23:44. Показов 20888. Ответов 11
Метки нет (Все метки)
Вот, например, пишу класс и всегда помню советы типа "скрывайте реализацию класса" или "если функция по идее не должна изменять данные класса, то сделайте ее const ".
Почитал про итератор тут http://www.insidecpp.ru/patterns/iterator/ Прочитал то, что пишет ValeryLaptev Итератор ? Почитал на wiki. В книге Дейтелов почти ничего про это нет. Но не понял как пишется более менее нормально итератор. Единственную реализацию итератора, которую знаю, эта которая по первой ссылке. Но т.к. я не знаю как правильно писать итератор, то мне кажется эта реализация кривыми. Может там все грамотно написано, но я не могу это принять. Т.е. если я буду писать итератор, то я буду писать то, что сразу в голову придет, не задумываясь правильно я делаю. Буду писать говнокод. Где можно посмотреть нормальную реализацию итератора? Хотелось бы в двух видах, т.е. в виде iter.next()(функция) и ++iter(как указатель), как в первой ссылке. И где почитать можно на русском.
0
|
|
| 17.09.2011, 23:44 | |
|
Ответы с готовыми решениями:
11
Написать свой итератор, чтобы алгоритмы STL работали с моим классом Как можно получить итератор на элемент обрабатываемый в лямбде в функции for_each?STL Найти вероятность того, что герб выпадет: 2 раза; не менее 2 раз; не более 2 раз; не менее одного и не более трех раз |
|
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
|
|
| 17.09.2011, 23:50 | |
|
Chelioss, в книге Банды четырех, вестимо...
1
|
|
|
186 / 186 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
|
|
| 17.09.2011, 23:53 [ТС] | |
|
0
|
|
|
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 18.09.2011, 00:03 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Сообщение было отмечено как решение
Решение
Вот еще из моих материалов.
Надеюсь, что даже в таком виде это поможет разобраться. Итератор для последовательного контейнера Для дека нам потребуются конструкторы и деструктор. Минимально необходимое множество операций включает операции добавления элемента в начало и конец дека, операции удаления первого и последнего элемента. Еще необходимы функция проверки, есть ли в контейнере элементы, и функция, выдающая количество элементов в контейнере. Обычно в состав методов включают и методы получения значений первого и последнего элемента контейнера. Рассмотрим более подробно операцию доступа к элементам контейнера. Так как внутренняя структура элемента скрыта, поскольку прописана в приватной части класса-дека, программа-клиент не сможет работать с элементами контейнера посредством указателей. Для перебора элементов контейнер должен обеспечить последовательный доступ к элементам другим способом. Это можно сделать двояким образом: 1. либо реализовать методы доступа непосредственно как методы контейнера; 2. либо инкапсулировать все операции доступа в отдельный класс-итератор. Второе решение предпочтительней хотя бы потому, что позволяет отделить интерфейс доступа от интерфейса контейнера. Это позволит в дальнейшем иметь один и тот же универсальный интерфейс доступа для разных типов контейнеров. Таким образом, итераторы играют очень важную роль при инкапсуляции информации контейнеров. ВНИМАНИЕ Именно таким образом реализованы итераторы в стандартной библиотеке шаблонов STL. Это одно из решений, оказавших существенное влияние на состав и структуру стандартной библиотеки. Класс-итератор можно реализовать как отдельный независимый класс. Но так как итератор должен иметь доступ к внутренней структуре элемента контейнера, он должен с этим классом «дружить». Очевидно, что итератор очень тесно связан с внутренней организацией контейнера, поэтому лучше его реализовать как вложенный класс [1-9.7] класса-контейнера, как и класс-узел. Поскольку программе-клиенту потребуется создавать объекты-итераторы, этот класс должен быть определен в открытой части класса контейнера. Назовем класс-итератор именем iterator. Мы нарушили собственное правило начинать имя класса с буквы Т только потому, что при создании итератора программа-клиент обязана будет указать префикс — имя объемлющего класса, например
Значение итератора представляет собой позицию в контейнере. Набор операций с итераторами фактически уже описан нами выше (см. выше раздел «Доступ к элементам контейнера»), однако полезно еще раз на этом остановиться. Итак, класс-итератор должен обеспечивать следующий минимальный набор операций: - * — получение элемента в текущей позиции итератора; - = — присваивание итератора; - == и != — проверка совпадения позиций, представленных двумя итераторами; - ++ — перемещение итератора к следующему элементу контейнера. Итератор с таким набором операций в стандартной библиотеке называется прямым. Если мы добавим операцию перемещения к предыдущей позиции (декремент --), то получим итератор, который в стандартной библиотеке называется двунаправленным. Отметим, что набор операций двунаправленного итератора соответствует множеству операций с указателями при переборе элементов массива. Это позволяет одинаковым образом обращаться и с массивами, и контейнерами. Однако надо отметить, что встроенные указатели, по выражению Д.Элджера [25], являются «глупыми», тогда как итератор мы можем сделать настолько «умным», насколько пожелаем. Для того, чтобы начать перебирать элементы контейнера, итератору надо присвоить первоначальное значение на первый элемент контейнера. Обычно для этого в контейнер включают метод begin(), который в качестве результата возвращает итератор, установленный в начало последовательности элементов контейнера. Метод end() возвращает итератор, установленный в конец последовательности элементов контейнера. Что считать концом последовательности, составляет важный вопрос реализации. По примеру STL (STL — прекрасный пример для подражания!) будем считать, что концом последовательности является позиция за последним элементом последовательности. Таким образом, пара методов begin(), end() определяет полуоткрытый интервал, который содержит первый элемент, но выходит за пределы последнего элемента. Это в точности соответствует ситуации, описанной нами при реализации конструктора класса TArray (см. листинг 3.3). Полуоткрытый интервал обладает двумя достоинствами: - не нужно специально обрабатывать пустой интервал, так как в пустом интервале begin() равно end(); - упрощается проверка завершения перебора элементов контейнера — цикл продолжается до тех пор, пока итератор не достигнет позиции end(). Для реализации полуоткрытого интервала в контейнер обычно добавляют «пустой» фиктивный элемент, не содержащий данных. Реализация контейнера-дека Обратимся теперь непосредственно к реализации. Сначала покажем составляющие класса TDeque, а затем всю его структуру. В листинге 3.19 представлена приватная часть класса.
Чтобы не отвлекаться от главной задачи — изучения доступа посредством итератора, — мы объявили конструктор копирования и операцию присваивания закрытыми. Да и нет особой необходимости (пока) присваивать деки. Наличие объявления приводит к тому, что компилятор не будет создавать эти функции по умолчанию. Таким образом, мы запретили создавать копии контейнера-дека и присваивать один дек другому. Следствием является так же и то, что контейнер нельзя передавать по значению в качестве параметра и возвращать в качестве результата. Далее объявлены поля класса TDeque: счетчик элементов контейнера, реальные указатели на начало и конец списка. Счетчик увеличивается при каждом добавлении элемента и уменьшается при каждом удалении элемента. Поля-указатели никогда не равны 0, так как даже в пустом контейнере присутствует запредельный фиктивный элемент А вот программе-клиенту указатели недоступны — она работает с итераторами. Следовательно, нужны аналогичные поля для класса-итератора, которые этим классом и инициализируются. Сам класс-итератор (листинг 3.20) прописан в открытой части класса TDeque.
Хотя мы не обрабатываем ошибки , тем не менее, операции продвижения не приводят к непредсказуемому поведению программы — при некорректном указателе продвижение просто не выполняется и возвращается текущий итератор. В операции разыменования operator * указатель на элемент проверяется на ноль. Эта проверка необходима, так как в классе-итераторе есть конструктор по умолчанию, обнуляющий этот указатель — программа-клиент ведь может объявить итератор, но не инициализировать его. ПРИМЕЧАНИЕ Вообще-то говоря, мы можем сделать этот конструктор приватным — тогда пользовательская программа не сможет создавать нулевые итераторы. Естественно, и проверка на ноль тогда будет тоже не нужна. Все методы удобнее реализовать именно внутри класса, так как при реализации вне класса (и вне класса TDeque), придется писать слишком длинные префиксы. С учетом всех этих соображений класс TDeque, представленный в листинге 3.21, выглядит следующим образом:
Во-вторых, мы непосредственно в классе объявили два конструктора с практически идентичным телом. Почему бы во втором конструкторе не использовать первый, как мы обычно поступали, например
Рассмотрим теперь реализацию операций вставки и удаления в начале дека (листинг 3.22).
В листинге 3.23 показана реализация операций вставки и удаления элементов в конце дека. И здесь тоже необходимо самым внимательнейшим образом отследить порядок работы с указателями. Кроме того, обратите внимание на то, что в данном случае не требуется корректировать итератор, так как указатель Tail фиксирован и никогда не изменяется — он всегда указывает на запредельный элемент.
Проверить работу операций вставки и удаления, а также доступа к элементам по итератору, можно, выполнив программу, представленную в листинге 3.25.
Результат программы соответствует комментариям:
9
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
|
||
| 18.09.2011, 12:50 | ||
|
1
|
||
|
программист С++
860 / 600 / 147
Регистрация: 19.12.2010
Сообщений: 2,014
|
||||||
| 18.09.2011, 13:49 | ||||||
|
вот мой совместимый с STL итератор для вектора
1
|
||||||
|
186 / 186 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
|
|
| 18.09.2011, 17:04 [ТС] | |
|
У меня есть вопрос про итератор по первой ссылке.
Тип T - это понятно. Будет, например, int, тогда везде вместо T "подставиться", грубо говоря, int. Например, в методе begin контейнера создается итератор и в зависимости от типа указателя, итератор подменяет T на какой-то тип. Итератор it в main от метода begin получает итератор определенной T специализации и итератор it принимает такой тип T. А что за тип node? Откуда он берется? Как его компилятор определяет? По идее же конструктор iterator должен принимать T * n, а он принимает какой-то тип node * n.
0
|
|
|
186 / 186 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
|
||
| 18.09.2011, 17:20 [ТС] | ||
|
1)Вот что по первой ссылке будет вставляться вместо node, если контейнер содержит в себе элементы string? Я так понимаю, что вместо T будет тип string, а что вместо node? 2)Если я пишу свой шаблонный итератор, то мне тоже надо делать два типа, т.е. node и T?
0
|
||
|
|
|||
| 18.09.2011, 17:24 | |||
|
Если контейнер - это вектор (элементы в памяти хранятся последовательно), то node не нужен, так как достаточно двигать указатель на элемент. Если связный список, то node это узел списка. А без него "шагать" не получится.
1
|
|||
|
186 / 186 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
|
||||||||||||||||
| 18.09.2011, 17:36 [ТС] | ||||||||||||||||
|
1)А можно написать вместо класса итератора по первой ссылке класс итератор с 1 типом, т.е.
:
Так? Если по первому вопросу я правильно сказал, то можно неиспользуя тип node, перед iterator it не писать string_container::?
0
|
||||||||||||||||
|
|
||
| 18.09.2011, 17:39 | ||
1
|
||
| 18.09.2011, 17:39 | |
|
Помогаю со студенческими работами здесь
12
STL итератор на конец контейнера
Как правильно вернуть итератор из метода
Как сделать более-менее точный секундомер? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ВВЕДЕНИЕ
Введу сокращения:
аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
|
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi
ветка по-частям.
коммит Create переделка под биомассу. txt
вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
|
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ *
Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях.
Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её.
Последовательность действий:. . .
|
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
|
|
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение.
И на уровне агентов добавится между грибами или бактериями взаимодействий.
До того я пробовал подход через многомерные массивы,. . .
|
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Налог на собак: https:/ / **********/ gallery/ V06K53e
Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf
Пост отсюда. . .
|
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop?
Ниже её машинный перевод.
После долгих разбирательств я наконец-то вернула себе. . .
|
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод
Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод.
Thinkpad X220 Tablet —. . .
|