Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 120
Текст из файла (страница 120)
ф 17.3.3). Данное сравнение — это сравнение ключей, но па!не !уре контейнера тар— Глава 17. Стандартные контейнеры 544 это пара !ключ, значение). Поэтому функция оа!ие сотр () определена так, чтобы срав- нивать пары, используя функцию сравнения ключей 1етр!а1е<с1аккКеу, с1акк Т, с!акк Стр = 1екк<Кеу>, с!аккА = айасагог<ран солИКеу, Т» > с!акк тар ( риЫ(с: 1урес!е/ Стр Ьеу сотраге; с!акк па!ие сатраге; риЬИсЬтагу 7ипс11ап<оа1ие 1уре., иа1ие 1уре, Ьоо!>( /пепд с1акк тар; рга1ес1ес); Стр стр, иа!ие сотраге (Стр с); стр (с) () риЫ!с, Ьоа1 орегагог() (солк1 иа(ие 1урей х, солт оа1ие 1урей у) сапк1 ( ге1игп стр (х Якг, у. Йгк1); ) Ьеу сатрагеуеу сотр !)солк1; иа!ие сотраге па!ие солтр () солк1; Например: тар к1ппд, !п1> т1; тир<к!пад, 1л1,)уасаке> т2; //определяет тип сривненик 1К !714!) тир<к!пад, !п1, 51гмд слюр> тд; //определяет тил сравнения 72 !7.!.4Л) тор<к!пад, т1, В!пад стр> т4(5!пад стр (Игегагу)); //передается сравнение оо!ИЯтар<к1ппд, 1лс>й т) тар<к1г!пд, ш1> т2; тар<ккг(лд,!л1 тд (т.уеу сотр()); //...
// ло умолчанию сравнивается при нолти(и < // сравнивается тик, ник кто дели ет т Как определить особое сравнение, см, в ~ 17.1.4,1; описание объектов-функций при- ведено в (( 18.4. 17.4.1.6. Операции с ассоциативными массивами Главная идея ассоциативных массивов, а в действительности и всех ассоциативных контейнеров, — получать информацию по ключу. Для этого введено несколько спе- циализированных операций: 1етр1а1е<с1акк Кеу, с!акк Т, с!акк Стр = 1екк -Кеу>, с!акк А = ауоса1аг<ра!г сапк1Кеу, Т» > Ыакк тар ( риЫ(с: Функции-члены аеу сотр () и оа1ие сотр () дают возможность запросить ассоциа- тивный массив о способе сравнения ключей и значений. Обычно это делается, чтобы обеспечить тот же критерий сравнения для некоторых других контейнеров или алго- ритмов.
Например: 1?.4, Ассоциативные контейнеры // операции с ассоциакшвнылш массивами // находит элемент с ключом 6 Иега1огЯпд (сопя! Ьеу 1урей Ь); сопк1 Иега1ог/) пй (сопк1 Ьеу 1урей й) соля1; // ноходшп чшло элементов с ключом Ь яссе 1уре соип1(сопк16еу 1урей Й) сопя1; О находит перона элел~е>ип с ключах~ Ь Иегагог!ожег Ьоипд(сопя1 Ьеу 1урей Й), солИ нега!ос!ожег Ьоипд(солИЬед 1урейЬ) соля1; // находил первый элемент с ключах~ болыие чем Ь Иегаеог иррег Ьоипс( (сопя! дед 1урей Ь); сопя! Иега1огиррег Ьоипд(сопя1 Ьеу 1урей й) сопк1; расг<Иега1ог, Иега1ог> еуиа1 галде (сопя! Ьеу 1урей), раи сопк1 11ега1ог, сопИ Иега1ог> еуиа! галде (соля1 Ьеу 1дрей) сопя!, тар<ИИпу, !пг>спега1ог р = т/(лд (' Золото' ); (!' (р!=т.епд ()) ( //...
е!ке у' (таад (" Серебро")(=твид ()) ( //... ) //.- О ес,ш 'Золото' найдено // ищем "Серебро' Для гпи/Итар !й 17.4.2) нахождение первого вхождения редко так полезно, как нахождение всех вхождений; функции т )оаег Ьоипс!(Ь) и т.иррег Ьоипс! (Ь) дают начало и конец подпоследовательности элементов контейнера т, имеющих ключ Й. Обычно конец последовательности — зто итератор, указывающий на элемент, следующий за последним в последовательности. Например: ио!<11 (ти!11тар<к1г1лд, (п1>й т) ( тиИ1тар<к1ппу, (пс эИега1ог 16 = туохеег Ьоипд (" Золото' ); тай!тир<котлу, !п1>сйега1ог иЬ = т.иррег Ьоипд (" Золото ); )ог (ти!Итар<ИИпу, !п1>..Иега1ог р = !6; р!=и6; к+р) ( Операция туспг! (Ь) просто выдает нтератор, соответствующий элементу с ключом Ь.
Если такого элемента не существует, возвращенным итератором будет т.епс( (). Для контейнера с уникальными ключами, такого как тар нли яе1, результирующий итератор будет указывать на единственный элемент с ключом Ь. Для контейнера с не- уникальными ключами, такого как гпи/1!тар >щн гпи!1!ке1, рсзультирующий итератор будет указывать на первый элемент с таким ключом. Например: оогд! (шар<к!ггпу, т1>й т) ( 546 Глава 17. Стандартные контейнеры Нахождение верхней и нижней границ двумя отдельными операциямн не изящно и не эффективно. Операция ес(иа( галде (] предназначена для предоставления обоих. Например: ооиЦ(ти(йтар<к1ппу, тг й т) ( 1уредел" ти(1(тир<к(г(пу, (п(>.,((ега1огМ1; ра(г<М1, М!> д = т.еуиа( гапуе ("Залов!о').
/ог (М! р = у!(гк(; р!=укесопс(;.нр) ( //- ) Если 1осоег Ьоипс(((е) не находит (с, она возвращает итератор на первый элемент с ключом больше (г или епс( (), если такого элемента нс существует. Этот способ сообщения о неудаче также используется функциями иррег Ьоипс( () и едиа! галде ().
17.4.1.7. Операции со списками Вводить значения в ассоциативный массив принято простым присваиванием с ис- пользованием индексации. Например: рбопе Ьоо(л('Отдел заказов' ) = 8228389; Это гарантирует, что об отделе заказов будет занесена соответствующая запись, независимо от того, было ли в телефонной книге что-либо об отделе заказов до того. Также можно вставить элемент функцией спкег( () и удалить функцией егаке (): 1етр!а1е<с1акк Кеу, с1акк Т, с(акк Стр = !екк<Кеу>, с1аккА =а((оса(ог<ра(с<сопя(Кеу, Т» с!акк тар ( риЫ(с: О-. // операг(лглл со спискалш: О встивляет пару (ключ, значение) раи Пега1ог, Ьоо!> !пкег1 (соне( иа1ие (урей оа!), //рок — зто только подсказка, с какого песта искить Пега(ог (оке!! (Ыега1ог рок, сопя( ьа(ие (урей оа(); //встовляеи! злелгенты из последовательности 1етр1а1е <с1акк !и> поЫ (пкег( (1п !( гк1, 1п (ак(); //удаляелп зле>~сит, ни который указивает втерптор оо(с(егаке (иега1ог рок), // удоляеп! злепент с ключои (г (если такой злелгент существует) ксее !уре вгике (сопя!(леу 1урей(л); // удаляет диапазон оо(д его ее ~(!(его!о г/) гк1, Пега(ог (акЯ, оо(с( с1еаг (), Операция т.лпкег( (оа1) пытается добавить в и пару па!типа (Кеу, Т).
Поскольку ассоциативные массивы — это контейнеры с уникальными ключами, вставка производится, только если в т не существует элемента с таким ключом, Возвращаемое 547 17.4. Ассоциативные контейнеры значение тлляег! (иа!) — это пара ра!г<!!ега!ог,боо!>. Переменная типа боо! принимает значение ггие, если оа! действительно вставилось. Итератор указывает на тот элемент контейнера т, который имеет ключ оа1,/7гя!. Например: ооЫ/(тар<игппу, !пг>Ь т) ра!г<иигтд, т! р99 ('Павел', 99); рагг<тар<игПпу, !лГ сЫегаиог, Ьоо!> р = тйлиеги (р99); (/ (р.иесолд) ( ///" Павел' был валаилен е!ие ( // "Павел уиее был тал ) тар и!г!пу, !пвклиегаиог1-р йгий //указывает на т/ Павел ! Обычно нас не заботит, вставлен ключ заново или уже присутствовал в ассоциативном массиве до выполнения (ляег! ().
Когда это нас все же интересует, то лишь потому, что мы хотим зарегистрировать тот факт, что значение оказалось в массиве откуда-то извне. Две другис версии !лиег! () нс возвращают признака, действительно ли значение вставилось. Указание позиции роя в !ляег! (роя, па!) — это просто подсказка реализации. откуда начать поиск ключа оа7,/йгяб Если подсказка хороша, то можно значительно выиграть в производительности.
Если нет, вам лучше обойтись без цее, с точки зрения как эффективности, псам и краткости в записи. Например; оогд/(т ар<иггту, !пг>й т) т["Дмитрий") = 3; // хотя, возлюжно, иенее з4хьек~пивно т тиег! (т Ьецт (), табе раи (соли!и!ггпу(Давид" ),99)'; //плохо Фактически, оператор [) — это болыпе, чем просто более удобное обозначение (ляег! (). Результат т[л) эквивалентен (*(т!ляег! (тайе ра!г (/еУ ())) ргя!))яесолг!, где У() — значение по умолчанию для отображенного типа. Поняв эту эквивалентность, вы, вероятно, поймете суть ассоциативных контейнеров.
Поскольку оператор [) всегда пользуется У(), нельзя использовать индексацию с типом значения, пе имеющим значения по умолчанию. Это печальное ограничение для стандартных ассоциативных контейнеров. Однако требование иметь значение по умолчанию не является фундаментальным свойством ассоциативных контейнеров вообще 1см. Э 17.6.2). Элементы с заданным ключом можно удалять. Например: ооиЦ(тар<игппу, ти>й т) !п! соил! = рбопе Ьоой.егаие ('Роя<ил')' Возвращенное значение типа !л! — это число удаленных элементов. В частности, если нет ни одного элемента с ключом "Роман, соил! становится равным О.
Для контейне- 548 Глава 17. Стандартные контейнеры ров ти!1!тар и ти!1!яе! это значение может оказаться болыпе !. В качестве альтернативы можно уда.лить э.лемент, на который указывает итератор, или удалить целый диапазон элементов, зная последовательность.
Например: оо!г!у(тар<к1апу, т1>йт) т.егаве (тяпЫ (гЕнатерина")! т.егаие (тату (' Алиса ), т/тд ('Влади>нар"Ц Естественно, быстрее удалить элемент, дпя которого уже имеется итератор, чем сначала найти элемент по ключу, и лишь потом улалить. Носле операции егаве () этот итератор не может использоваться снова, поскольку элемента, на который он указывает, больше не существует. Вызов т,егаяе (Ь,е), где е есть т.епс!(), безопасен !если Ь ссылается на элемент т илн на т.еле( ()1. С другой стороны, вызов т.егаяе (р), где р есть т.елЫ (), является серьезной ошибкой, способной погубить контейнер. 17.4.1.8. Другие функции Наконец, контейнер тар обеспечивает простые функции, выдающие число элементов, и предоставляющие специализированную форму <перемены мест > яшар (): 1е~лр!а1е<с!аяя Кеу, с1авя Т, с!авв Стр = !еяя<Кеу>, с!аявА = а!!оса!от -ра!г <сопя1Кеу, Т» > с1аяя тар ( ри6!1с: // //емкость. ясее 1уре я!ее () сопя1; // тало элементов в!ве 1уре тая в!ве () сопя1; О размер пансо вольно воэложного тор Ьоо! етр1у () сопя! ( ге!игл в!ее () == О; ) оои1 взвар (тарй); ); Возвращаемые функциями я!яе () и тах в!яе () значения — это чис.ло элементов.
Вдобавок, тар предоставляет операторы =,!=, <, >, <=, >= и функцию яшар () как функции-не-члены: гетр!а1е<с!акв Кеу, с1авя Т, с1авв Стр, с1акв А> Ьоо! орега1ог== (сопя1тар<Кеу, Т,Стр,А>й, сопв1тар<Кеу, Т,Стр,А й), //иналоганно !=, <, >, <= и >= Гетр(а1е<с!авв Кеу, с!аяв Т, с1авв Стр, с!пик А> иоау итар (тар<Кеу, Т, Стр, А>й, тар<Кеу, Т, Стр, А>й); Зачем кому-то сравнивать два ассоциативных массива? Когда мы особым образом сравниваем два ассоциативных массива, обычно мы хотим узнать, не только, различаются ли они, цо также, чем именно они различаются.
В таком случае мы не пользуемся == или (ьч Однако, обеспечив для каждого контейнера ==, < и яшар (), мы сделаем возможным написание алгоритмов, приложимых ко всем контейнерам. Например, эти функции позволяют нам рассортировать функцией вог! () вектор из ассоциативных массивов и получить множество с элементами типа ассоциативных массивов. 549 17.4. Ассоциативные контейнеры 17.4.2.