Я знаю, что это - вероятно, глупый вопрос.. Когда я должен был бы записать свой собственный итератор? Это как раз в то самое время, когда, разрабатывая мой собственный контейнерный класс? Есть ли какие-либо другие времена, когда я хотел бы создать свой собственный итератор?
Примеры были бы адаптированы.
- Jon
Да, бывает и в другое время. Вот несколько примеров:
Единственный раз, когда я писал итераторы на C ++, помимо фильтров и итераторов, я пытался заставить классы контейнеров сторонних производителей хорошо работать с алгоритмами stl. Например
В общем, я не люблю писать итераторы, потому что они сложны, и нужно о многом позаботиться. Однако эта задача значительно упрощается с помощью библиотеки итератора ускорения.
Реализация итераторов может быть чрезвычайно сложной. полезно, и я делал это довольно часто. Итератор - это простая концепция, которую каждый знает, как использовать. Итераторы позволяют использовать алгоритмы STL.
Часто вы можете реализовать итераторы, чтобы упростить использование часто используемых API-интерфейсов операционной системы, таких как Windows ' FindNextFile
Когда вы пишете file_iterator (уже существует в усилении), вы можете внезапно выполнить:
file_iterator itBegin; // initialize appropriately
file_iterator itEnd;
std::vector< HANDLE > vecFiles( itBegin, itEnd );
чтобы получить список дескрипторов для всех совпадающих файлов. Без итератора необходимые вызовы API затруднили бы чтение вашего кода.
Думайте об итераторах как о простых концепциях, которые позволяют вам написать то, что вы действительно хотите сказать, и абстрагироваться от мельчайших деталей.Если вам нужно реализовать сложный алгоритм, который трудно понять сам по себе, вы хотите уменьшить беспорядок в коде.
Если у вас двухмерная структура, например std :: vector
Я вижу два случая, когда вы хотите создать новый итератор:
every_3rd_iterator
, который возвращает только каждый третий элемент? Такой итератор, вероятно, будет реализован как адаптер вокруг существующего итератора. Вы также можете использовать их для перебора числовых последовательностей, таких как числа Фибоначчи или, возможно, простые числа. Это можно было бы сделать другими способами, возможно, более легко, но бывают случаи, когда использование итератора для таких вещей имеет смысл.
Вам нужно написать собственный итератор для вашего собственного класса контейнера или если вам нужно нестандартное поведение при итерации по стандартным контейнерам.
В любой момент, когда вам нужно выполнить итерацию по последовательности данных, а итератор, подходящий для ваших нужд, еще не определен.
Часто итераторы используются для обхода контейнеров, но это далеко не единственное их применение.
Итератор может также обходить результаты запроса к базе данных или входные данные, считанные из потока (std::istream_iterator
и std::istreambuf_iterator
уже делают это, однако), или, возможно, вам нужен специальный порядок обхода или стратегия. Возможно, вы хотите перебрать "каждый член этого вектора, чей индекс кратен четырем", или "каждую заглавную букву в этой строке", или все остальное, что вы можете придумать.
Когда у вас есть класс (скорее всего, контейнер) и вы хотите позволить своим пользователям удобно перемещаться по нему, не раскрывая деталей реализации, вы захотите создать итератор.
Это еще более верно для случаев, когда у вас есть семейство классов (опять же, скорее всего, контейнеров), и вы хотите предоставить своим пользователям единый интерфейс итерации/обхода для всех этих классов, даже если их реализация сильно отличается (например, связный список против массива).