Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 121
Текст из файла (страница 121)
Две другие версии функции йтег(( ) не возврашают никаких признаков успешности выполнения операции вставки. В вызове !лзег((рол, ва!) позиция ров — это просто попытка подсказать реализации, где нужно начать поиск ключа ва!. 7!гв(. Если подсказка хороша, то можно значительно выиграть в производительности. Если нет, то лучше бы ее вообше не применять (и с точки зрения эффективности, и с точки зрения чистоты записи).
Например: гоЫ ! (тор<в(г(пе, т(>В (и) ( (и [ "!(одЬег(" ] = 3( 0локонично и четко, но возможно менее эффективно т. тле(((т. Ьее(п (), та((е ра(г(соим в(г(ие( "]ЗодЬег(" ), 99) )'(,((уродливо ) Фактически, операция [] — это не просто более удобное обозначение для !ивег(() . Результат выражения т [7(] эквивалентен результату выражения (* (т.
!лвег((та((е раи (!(, Р() ) ) .Я(з() ) . лесот(, где Г() есть умолчательное значение для отображенного типа. Поняв эту эквивалентность, вы поймете суть ассоциативных контейнеров. Поскольку операция [1 всегда использует Р(), нельзя применять индексацию для ассоциативных массивов с отображенными значениями типов, не имеющими умолчателъных значений. Это неприятное ограничение для всех стандартных ассоциативных контейнеров (оно не является фундаментальным ограничением ассоциативных контейнеров вообще; см. З]7.6.2). Элементы с заданным ключом можно удалять. Например: кой(!'(тор<в(г(пе, (п(>в т) т( соил( = т егале ("Ка(Ьег(" ) 886 Глава 17. Стандартные контейнеры Возвращаемое значение типа зпг означает число удаленных элементов. В частности, здесь число О означает, что нет подлежащего удалению элемента с ключом пала!Ьегг". Для ассоциативных контейнеров типа та!итар и та!гиег возвращаемое значение может быть больше едапаз(ы.
Также имеется возможность удалить элемент, указуемый итератором, или диапазон элементов, начало и конец которого фиксируются двумя итераторами. Например: гоЫ а (тор<я!с!па, 1пг>з т) ( гп. егазе (т.3тд (" Са(Ьег(" ) ); т.егаяе(т.Япд[ "А11се"),т 4ин1[ "Иайу") ) ) ) Естественно, что быстрее удаляется элемент, непосредственно указуемый итера- тором, поскольку иначе сначала еше нужно найти его по указанному ключу, и лишь затем удалить. После выполнения операции егаяе () итератор становится недействительным, ибо элемент, на который он указывал, больше не существует. Вызов т.
егазе (Ь, е), где е есть т. епз!(), безопасен (при условии, что Ь ссылается на действительный элемент контейнера т, или на т.ет1() ). С другой стороны, вызов т. егазе (р), где р есть т. епд(), является серьезной ошибкой, способной испортить контейнер. 17.4.1.8. Другие функции Наконец, ассоциативный массив тар предоставляет и традиционные функции, имеющие дело с числом элементов, а также функцию яеар (): гетр!аге<с!азя Кеу, сгат Т, с!ая Стр = 1езя<Кеу>, с1аяя А = айосагог<ра!г<сопяг Кеу, Т» > сгая тар ( риЬКс: УУ ... УУ емкость: язе гуре я!зе() сопя!; УУ число элементов я)зе 1уре тазе яяе() сопя!! УУрозмер максимально возможного тар Ьоо! етряу() сопя! (ге!ига яяе () ==О; ) гоЫ знар (тара ); Как обычно, возвращаемые функциями я(зе() и так я1зе() значения есть число элементов.
Для контейнера шар операции ==, ! =, <, >, <=, >= и ягар () представлены глобальными шаблонами (а не функциями-членами); гетр(аге<сгат Кеу, с!ая Т, с!азя Стр, с(аяз А> Ьоо( орегаыг== (сопя! тар<Кеу, Т, Стр,А>ь, сопя тар<Кеу, Т, Стр,А>а) УУаналогично 1=, <,>, <=, н >= гетр!аге<с!азз Кеу, с!аи Т, с1аяя Стр, с!вяз А> гоЫ явор [пзар<Кеу, Т, Стр,А>а, тар<Кеу, Т, Стр,А>а) ) 17.4. Ассоциативные контейнеры 587 Зачем может потребоваться сравнивать два контейнера типа тар? Ведь когда мы специально сравниваем два ассоциативных массива, мы не интересуемся фактом их различия, а тем, как именно они отличаются.
И тем не менее, обеспечив каждый контейнер операциями ==, < и взвар (), мы сделаем возможным написание алгоритмов, применимых к любому контейнеру. Например, эти функции позволяют сортировать функцией зогг() вектор элементов типа п)ар, а также позволяют реализовать контейнер зе! с элементами типа тар. 17.4.2. Ассоциативный контейнер птм11)итар Контейнер ти!итар похож на тар, но он допускает дублирование ключей: гетр)аяе<с1аяя Кеу, с)аяя Т, с!аяя Стр = (еяя<Кеу>, с1ат А = ааоса!ог<раи< сопя! Кеу, Т» > с1аяя яг4:: тийипао ( риЫ!с: 77 как тар, за исключением: йега(ог 1пзеп(сопзг га!ие (урез); 77возвраи(ает йегогог, а не ран г7 нет операции индексирования !) ): например (для сравнения с-строк используем сззг)ик 1езя из 517.1.4.1) ко14Ятар<сйаг*, тг, Сзгппд 1еяз>я т, ти!итар<слег*, й», Сяйтя 1езз>я тт) Г т.йтеп(тале ра»("х",4) ); т.1пзегг(тайе ра1г("х",5) ) ! 7)эффекта нет: уэгсе есть вход дзл "х" Я!74!.7) У здесь т1"х'7 == 4 гпт.тзеп(тале ра1г("хч,4) ); та Апзеп(тайерагг("х",5) ); 77 тт содерзкит как ("'х",4), так и !"х",5) ) Это означает, что ти!итар не поддерживает индексацию по ключу так, как это делает тар.
Операции едиа! гаиКе(), !опек Ьоииг!() и иррег Ьоит!() являются (в17.4.1.6) основными средствами доступа ко множественным значениям по единственному заданному ключу. Естественно, для случаев, когда несколько значений могут соответствовать единственному ключу, ти!итар более предпочтителен, чем тар. В некоторых отношениях, тиййпар даже чище и элегантнее, чем тар. Поскольку у человека запросто может быть несколько телефонных номеров, хорошим примером применения ти!итар является телефонная книга. распечатать номера телефонов из телефонной книги можно, например, следующим образом: гоЫ рппг питЬегз (сопя! ти!итар<в»!пк, )пг> я рйопе Ьоо)я) ( (уреде! ти)итар<я!ппд, (п!>:: сопт йегагог 1; рай<1, 1> Ь = рйопе Ьоо)г.
е4иа! гапке ( "Я!гоня(гир" ); уйг(11= Ь.))гзз; 1 (= Ь.засол»; -и1) сои!« 1->яесоп» « 'тп'; 588 Глава 17. Стандартные контейнеры Для ти!итар аргумент операции имег!() всегда успешно вставляется в контейнер. Поэтому ти!итар:: !ияегг ( ) возвращает итератор, а не пару ра!г<!гега!ог, Ьоо)>, как в случае с тар. Ради однородности библиотека могла бы обеспечить для контейнеров тар и ти!итар общую форму операции !ияегг(), несмотря нато, что Ьоо! был бы для тий!тар избыточным. Еще одно проектное решение могло бы предоставить простую операцию !ияегг(), которая не возвращала бы Ьоо! для обоих контейнеров, а пользователям тар предоставляла бы какой-нибудь иной способ сигнализации об успешности операции.
Это тот случай, когда разные проектные идеи вступают друг с другом в противоречие. 17.4.3. Ассоциативный контейнер ве1 Ассоциативные контейнеры яе! (мноисества) можно рассматривать как ассоциативные массивы (з)7.4.1), для которых значения не важны и отслеживаются лишь ключи. Это приводит к незначительным изменениям в пользовательском интерфейсе: <етр!а!е<с1ат Кеу, с(ат Стр = 1еяя<Кеу>, с1ат А = айосагог<Кеу» <1аяя яи(:: яе! ( риЫ(с: //как тар, за исключением: Гурейег Кеу га1ие (уре; // сам ключ является значением гурейеу Стр га(ие <отроге; /нет операции индексирования !1 )' Определяя га!ие гуре как тип ключа (1сеу Гуре; см.
З! 7.4.1.1), мы совершаем небольшой трюк, позволяющий практически идентичному коду работать и с контейнерами тар, и с контейнерами яе!. Обратите внимание на то, что множества полагаются на операцию сравнения (по умолчанию <), а не на операцию равенства ==. Это означает, что эквивалентность элементов определяется через неравенство (э17.1.4.1), и что итерирование по контейнеру яе! выполняется строго в определенном порядке. Как и тар, контейнер яе! предоставляет операции ==, (=, <,>,<=,>= и я!гар() .
17.4.4. Ассоциативный контейнер птыШвет Контейнер ти!ияе! — это то же множество яег, но допускающее дублирование ключей: (етр(а!е<с(ат Кеу, с1ат Стр = !еяз<Кеу>, с(аяя А = айова!ог<Кеу» с(ат яМ:: тииаег ( риЫ1с: //как зе(, за исключением: йега<ог!ляегг(солт га(ие гуреа) ! Увозвратает пега(ог, а не рагс ): Операции едва! гаийеО, !обжег Ьоит!() и иррег Ьоиие!О являются Я\7.4.1.6) основными средствами доступа ко множественным вхождениям ключа. 589 17 5 «Почти контейнеры» 17.5. вПочти контейнеры» Встроенные массивы (95.2), строки типа латая (глава 20), массивы га!аггау (922.4) и битовые поля ььвег (817.5.3) содержат элементы и, следовательно, могут считаться контейнерами.
Однако все они не дотягивают до стандартного интерфейса контейнеров, так что эти «почти контейнеры» не полностью взаимозаменяемы со стандартными контейнерами вроде гесгог или 1!хг. 17.5.1. Строки типа я1ппд Тип Ьаяс згг!аа обеспечивает индексацию, итераторы произвольного доступа и большинство удобств, предоставляемых стандартными контейнерами (глава 20). Однако Ьаяс ха!аа не допускает широкого выбора типа элементов.