Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 138
Текст из файла (страница 138)
Если 1п есть итератор произвольного доступа, вычесть у)гм из 1ам. 2. Иначе инкрементировать итератор от Ягш до !аяг и вычислить расстояние. Эти альтернативы можно реализовать парой вспомогательных функций: !егнр1аяе< с1аяя 1и > гурепате Йегасог ггайя<1п>:: йфегепсе (уре и!я! де!рея(1пу)гяя, !и 1аяя, !нри! вега(ог гад) ( !уреиате !!его!ог иа!яя<1п>:: йЯегепсе туре я( = От 19.2. Итераторы и последовательности 661 шИ1с (1(гя(+ь ! = (ая() ((++; УУ используем только инкрсмснт гв(иги <(< ) <етр!а<в<с(азя Каи> <урспате йега<ог <га!м<Кап>: (<((фвгвпсв (урс сля( йе1рвг(Каи)(гя(, Кап (аз<, гоп<(от ассе(я йега<ог (ад) ( ге<игл !ая<-у(гя« УУ полагаемся на проиявольныб доступ Указанные с помощью теговых классов типы итераторов-аргументов позволяют явным образом заявить, какой внд итераторов ожидается.
Категории итераторов используются исключительно при разрешении перегрузки; они не используются в реальных вычислениях. Так что этот механизм имеет отношение исключительно к этапу компиляции. Дополнительно к автоматическому выбору вспомогательной функции данная технология позволяет произвести немедленную проверку типов 6) 3.2.5). Теперь нам будет просто определить (1(я(апсе () посредством вызова соответствующей вспомогательной функции: (стр1а(в<с(аяя 1и> <урсаатв <(сга<ог <га!уя<1п>:: <(фегвпсв <уре <(!я<апов (1и !)гя(, !и 1аяп гс(игп <(!я< йс1рсг (!(гя<, (ая(, !<ега(сг <гтм<1п>:: 1<ега<ог са(слогу() ) ) гоИ!'( гвс(ог<!п<>я и, 1(я(«(оиЫс>ь Ы, (я<сват ((вга(ос<я<с(ид> ь Й1, !я<сват !<вга(о<<я<<(ид> ь !(1, аз<сват Йсга<ог<сйаг>ь оя1, оя<гват !<вга(ог<сйаг>ь оя2 ) <((я<вися ( и. Ьвл(п ( ), и.
вп<(( ) ) ( <((я<апов(Ы. Ьейтш (), й(. вп<(() ) < И(я<писа (!я1, !я2); гдя<апсв (оя1, оя2); У алгоритм с вычитанием (У алгоритм с инкрсмснтом УУ алгоритм с инкрвментом УУ сггог< ошибка в категории итсратора, УУ аргументы неверного типа для ау(< Ьс!рвг() В реальной программе, впрочем, вызов <1(я(апсе() для (я(геат йега<ог вряд ли имеет большое значение. Эффектом будет чтение входа с его последующим отбрасыванием и возврат числа отброшенных значений. Применение ((сга<ог <га(<я<л> <: (1ега1ог са(ейогу позволяет программисту предоставлять альтернативные реализации таким образом, что для пользователя (которому нет дела до деталей реализации) выбор подходящей для его структуры данных Чтобы вызвать <1!а( йе!рсг(), йегагог (га(<я<1п>::йсга(ог са<ейогу должно быть либо шрш йега(ог (аК, либо гаи<!ош ассеяя !(его<от (аК.
Однако нет необходимости иметьразные версии (((м йе!рег() для прямых и двунаправленных итераторов. Благодаря наследованию теговых классов эти случаи успешно обрабатываются К!м йе!рег(), принимающей в качестве аргумента шра< йега<ог (аК. Отсутствие версии для оа(ри< йега<ог (аК отражает факт бессмысленности <1!я(апсе ( ) для итера- торов вывода: Глава 19. Итераторы и аллокаторы 662 альтернативы выполняется автоматически. Другими словами, это помогает эле- гантно спрятать детали реализации за публичным интерфейсом. Встраивание же (!п)(п)пя) позволяет получить эту элегантность без дополнительных накладных рас- ходов во время выполнения программы.
19.2.4. Итераторы длн вставок Попытка направить выходной поток данных внутрь контейнера в место„указуемое итератором, предполагает, что последующие элементы контейнера могут быть переписаны. Это также может приводить и к переполнению, и к порче памяти. Например: гоЫГ(вес!ог<!лг> а и) 7)1! л (Ы.Ьея!п (),200, 7); ) П присваиваем 7 всем элементам э!(О/..(!99/ Если в контейнере Ы элементов меньше 200, то возникают проблемы. Для решения подобного рода проблем стандартная библиотека определяет в заголовочном файле <вега!ог> три шаблонных класса итераторов вставки' и три вспомогательных функции, упрощающих их использование: гетр!аге<с1аяя Сои!> Ьасй шяем вега!ог<Солг> Ьасй 1ияег!ег(Селга с); гетр!иге<с)аяя Сои!>!гоп! !пяегг йегагог<Соп<>!гоп! шяемег(Соыя с); гетр1аге<с1ат Сои!, с!аяя Ои!> (ияег! йегагог<Сош> 1пяеггег (Солса с, Ои! р) коЫ а (гесгог<шг>а Ы) ( (111 п(Ьасй 1пяеггег(Ы),200, 7) ! Удобовлнем 200раэ ло 7 в конец и' ) Итераторы вставок столь же просты и эффективны, сколь и полезны.
Например: гетр!а!е<с)ат Сои!> с1аяя шяег! 1(ега!ог: риЫ(с вега(ог<ои!ри! 1(егагог !ад, гоЫ, гоЫ, гоЫ, гоЫ> ргогесгеФ: Сои!я сои!а1иег! гурепате Сои!:: йегагог йег! риЫЫ: ехр1)сй шяегг вега!ог (Солса х, гурепате Сонг:: йегагог 1) : сопгашег(х), 1гегМ) () По стандартной классификации относятся к итераториым адаптерам. — Прим.
ред. При помощи функции Ьасй имег!ег() элементы вставляются (добавляются) в конец контейнера; при помощи функции 2(гоп! имег!ег () — в начало контейнера, а при помощи «просто» гпяеггег() — в место, указуемое ее аргументом-итератором. Для вызова 1ияеггег(с,р) р должно быть действительным для с итератором. Естественно, что с каждой вставкой контейнер растет. Итераторы вставок осуществляют вставку новых элементов в последовательность, применяя рпяй Ьасй(), рияй !гоп!() или 1пяег!() (516.3.6), а не посредством переписывания существующих в контейнере значений.
Например: ) 9.2. Итераторьв и последовательности 663 Гиле«< Йега(огь орегаГог= (соль< (урелате Солт<: та(ие (уреь та() ( Йет = сотатег.1лзе«Г(йег, та1) Г ььйе<ч ге<иги *ГЬЬГ ) !пзе«< в<его(огь арета<от* () ( «е(игп *ГЙЬ< (изет< 1(ега(огь арета<от++ () ( ге(игп *йиЪГ ) визе«< в<его<от орегаГотв" (вп<) ( ге<игл *<ЬЬГ ) )в У префиксный ма ГУ постфиксный ом Ясно, что итераторы вставок — это итераторы вывода. Класс !изет( <Гега(ог — это особый случай выходной последовательности. По аналогии с 1зеа из 518.3.1 мы могли бы определить Гетр(а(в< с(азз Сои(> !пзе«Г Пега<от<Сап<> озе<Г (Сои(ь с, <уреиате Соп(:: Йети(ог йгз<, (уреиате Сои<: в Йе«а(о«!аз<) ( ге<игл !иве«Г Йега<от<Соп(> (с, с.
егазе((в«з<, 1а<а) ) < У егазе разьясняется в,з!б.З.б Ясно, что выходная последовательность удаляет старые элементы и заменяет их на элементы вывода. Например: то<в( !'(1!з(<1п<>ь 11, тес(от<<и(>ь и) в)'заменяет вторую половину И копией Й ( сору(Й.Ьей(л (),!в'.еив((),озев((и',л'.Ьея<п () т 1.з<ье() !2, т<.еив(() ) ) < ) Аргументом озеа() должен быль именно контейнер, ибо уменьшить размеры контейнера невозможно, если располагать лишь итераторами на его элементы 518.6, 518.6.3).
рта<ее(ев( в йег сипел(; !<вигген< указывает на элемент, следующий за указуемым через *Гйвз риЬЙс: (уров(е( йег вГега<от <уре; «етегзе Йети<от() в сит«ел<() () Относятся к итераторным аааптерам. — Прим. ред. 19.2.5. Обратные итераторы Стандартные контейнеры предоставляют функции-члены «Ьея1и () и «си<1() для итерирования элементов в обратном порядке (816.3.2). Эти функции возврашают обратные итераторы' типа гегегзе в(его<он Гетр1а<е <с1азз йег> с(азз «етегзе Йепиогв риьйс Йега<ог<(урепате Йети<от Гттп<йег>: в Йега(ог са<еаогу, Гурепате дега<от (га<Ь<йег>:: та(иу (уре, <урепате Йега(от (га!уз<Пег>: в Йяегеисе (уре, <урепате Йети(ог (гайз<1<ег>: в рот<ег, (уреиате Йета(ог (Гааз<1<ее> в <ге!в«елее> Глава 19.
Итераторы и 'аллокаторы 664 ехрйсй гечегзе Йети<от(Пег х): сиггел((х) ( ) <етр(а<в<с(азз (7> гечегзе Йети<от(соля< гечегзе Йети<от<1)>з х) сигтеп< (х. Ьазе ( ) ) ( ) Пег Ьазе() сопи (те(итп сиггеп1< ) 77значение текущего итератора ге(егепсе арета<о«* () солз1 (Йег <тр = сиггеп<< ге<игл *--лир; ) рот<ег орете(ог-> () соил<< ге(егепсе орега1ог (1 (ЙЯегепсе <уре п) сопл(; гечетзе Йега<огь арета(ог««() гечегзе Йети(ог орете(от«+ (т1) течегзе вега(ого орете(ог-- () гечегзе Йега<ог арета<от †(1п<) (--сиггеп(; те<игл *<Ь!з; ) («ече«зе Йе«а(от< = слетел<; --си«теп(< тези«п « ) (+«сиггеп<< «е<итп *<Ь!1< 1 (гечегзе Йети<от( = сиггеи(< +«сиггел(1 ге(игл(< ) гечегзе Йега(ог оре«а<о(«(<(фегеисе 1уре п) сопи< гечетзе вега(ого орете<от«= (4(Г<егеасе <уре п); гечегзе Йе«а(ог орете(ог- (4Щегепсе (уре и) сопи< гете«зе Йети<о«а арета<от=- (((Де«елее (уре п); )< Класс тече«ее 1<в«а(от реализуется с применением поля сит«ел( итераторного типа.