Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 21
Текст из файла (страница 21)
3.7.2. Проверка допустимости диапазона Класс оес1ог из стандартной библиотеки по умолчанию не обеспечивает проверку диапазона Я 16.3.3). Например: ооЫД ( !л11=рЬопе Ьоод(!00!)питЬег; // !00! — вне пределов диопоэона 0- Это присваивание, скорее всего, поместит в ! какое-нибудь случайное значение, а не выдаст сообщение об ошибке. Это нежелательно, поэтому я воспользуюсь простой, проверяющей диапазон адаптацией класса оес1ог по имени вес. $ес во всем похож на пес!ос, ио он будет генерировать исключение типа ои! о!' галде, если индекс окажется вне пределов диапазона, Технологии реализации типов, подобных Уес, и эффективного использования исключений обсуждаются в 9 11.12, 9 8.3 и главе 14. Однако, приведенного здесь определения вполне достаточно для примеров в этои книге: 1етр!а1ек с!авв Т> с!авв (гес: риЬ!1с оес1ог<Т> ( риЬ!1с. %ес((; оесгогкТ>((() Уес(еп1в(; оессог Т>(в((( 90 Глава 3. Обзор стандартной библиотеки Т1, орска 1ог() ((п1 1) ( ге1игп а1 (л); ) // с проверкой диапазона сопв1 Тй орега1ог(1 (1л14 сопз1( ге1игл а1 (1); ) // с проверкой диапазона й Функция-член а1() — это операция индексирования вектора (то есть операция доступа к элементу вектора по индексу), которая генерирует исключение типа ои1 о/ капуе (из <зЫехсер(>), если ее аргумент находится вне пределов диапазона вектора(б 1633).
Возвращаясь к задаче о хранении имен и телефонных номеров, мы теперь можем воспользоваться Уес, будучи уверенными, что обращения вне диапазона вектора будут пер ех ваче ны. Например: Ъгес<Елггуь рЬопе ЬооЬ (1000) оо(дрып1 еп1гу (т1 1) //используел~ кик раньше ( сои1«рЬопе ЬооЬ(1).пате«''«рЬопе ЬооЬ(1)литдег«''~л'; ) Обращение вне границ диапазона сгенерирует исключение, которое пользователь сможет перехватить. Например: ооЫД 1гу ( Хог (л' = 0; л < 10000; 1жл) рпп1 еп1гу (1); сагсЬ (ои1 о/ галие) ( сонг « "выход за пределы диапазона10', ) Когда будет предпринята попьшка доступа к рйоле Ьоой[11 се 1000, будет сгенерировано, а затем и перехвачено исключение.
Если пользователь не перехватывает этот тип исключений, программа будет завершена хорошо определенным образом, а не продолжит выполняться непредсказуемо и пе повиснет. Одним из способов минимизации сюрпризов от исключений является использование та(п () с блоком 1гд в качестве тела функции: ал1 талл () 1гу ( // код програлшы са1сЬ (оиг о/ капуе) ( сегг "выход за пределы диапазона1п'; сагсЬ(.
)( сегг «сгенерировано неизвестное исключение',и Это обеспечит обработчик исключений по умолчанию. Таким образом, если мы пе перехватим какое-нибудь исключение, соответствукицес сообщение запишется в стандартный поток диагностики ошибок сеп (Ь 21.2.1). 3.7.3. Список Обычными операциями лля телефонного справочника являются включение и удаление номеров. Поэтому список (1(зс) — более подходящая (чем вектор) структура для представления простого телефонного справочника. Например: 91 3.7. Контейнеры (!М'Еп1гу рлопе Бооу; При использовании списка мы не применяем индексирование для доступа к элементу, как мы обычно поступаем с векторами.
Вместо этого осуществляется поиск элемента списка с заданным значением. Мы пользуемся тем, что список является последовательностью, как объяснено в 9 3.8: оо!е!рг!п1 еп(гу (еопз1 згг пуе к) ( 1урее!е/!!з1кЕпггу»ьеопз! 11егагогИ рог фХ1=рЬопе БооЬ.Беу1п (); П=рЬопе БооЬ.епг(();++6( еопз(Епй уй в = *1; О для краткости игпольэуетея ссылка Ц' (з == е.пате) ( еои1 «е.пате « ' ' «е питбег « '~п', ге1игп; Поиск вхождения з стартует с начала списка и продолжается до тех пор, пока либо не будет найден з, либо не закончится весь список.
Каждый контейнер стандартной библиотеки снабжен функциями Ьеу(п () и епе( (), которые возвращают итераторы на первый элемент и «элемент, следующий за последним» соответственно Я 16.3.2). Если имеется итератор 1, следующим элементом будет ++1. Если есть итератор 1, элемент, на который он ссылается„это "1.
Пользователю нет необходимости точно знать тип итератора стандартного контейнера. Тип итератора является частью определения контейнера и на него можно сослаться по имени. Когда нет необходимости изменять элементы контейнера, пужен итератор типа сопя! (1ега1ог..В противном случае пользуются обычным типом !1ега1ог Я 16.3. (). Добавлять элементы к списку или удалять их из списка очень просто: оо!е(аг!д еп1гу (Епй уЬ е, !!з!<Еп1гу»11ега1ог!, !!зг<Еп1гу»с!1ега1огр) раопе ЬооуризЬ /гоп1(е) //добавить к началу раопе Ьоой.ризЬ Ьаеа(е); //добавить вконец рЬопе ЬооЬ.тзег1 (Е е), Оветавить перед элементом *! // удачить элемент*р рЬопе Бооа.егаке (р); Более полное описание (пзег1 () и егазе () см. в 9 (6.3.6.
3.7.4. Ассоциативные массивы Писать код для поиска имени в списке, состоящем нз пар (имя, номер) — весьма утомительное занятие. Кроме того, последовательный поиск достаточно неэффективен за исключением очень коротких списков. Вставку, удаление и поиск значения непосредственно поддерживают другие структуры данных. В частности, в стандартной библиотеке имеется тип тар (9 17А.1). Тип тар является контейнером для хранения пар величин. Например: Глава 3.
Обзор стандартной библиотеки 92 тар<з1гспд, (пс> уделе Ьооу; В других контекстах тар называют < ассоциативным массивом» или «словарем». Будучи проинлексирован по значению первого типа (называемому ключол~), тар возвращает соответствующее значение второго типа (называемое значением или огпобралсениыл~ шипел~). Например: оои(рг!п1 еп!гу1уопз1зЫщйз1 ( (1уп11 раппе ЬооЫЯсои1«з«''«1«"~п'; Если для ключа з вхождение нс найдено, возвращается значение по умолчанию. Зна- чением па умолчанию для целого типа в тар является О. В нашем случае я предпол- гаю, что О не является допустимым телефонным номерам. 3.7.5. Стандартные контейнеры 14 тар, и йзб и оес(ог могут использоваться для представления телефонной книги.
Каждый из этих типов имеет свои сильные и слабые стороны. Например, доступ па индексу к элементу вектора прост и эффективен. С другой стороны, вставка нового элемента между лвумя соседи ими является для вектора повально дорогим занятием. Со списком все обстоит ровно наоборот. Тип тар реализует список пар (ключ, значение), но кроме этого он оптимизирован для поиска значения по ключу. Стандартная библиотека предоставляет самые общие и полезные типы контейнеров, что позволяет программисту выбрать контейнер, наиболее полно удовлетваряюший потребностям приложения: Стандартные контейнеры тар<йеу, оа1> ти(атар<йеу, оа1> Стандартные контейнеры описаны в 9 16.2, С1 16,3 и главе 17.
Контейнеры опрелелены в пространстве имен зЫ и прелставлены в заголовочных файлах <оестог>, <йз1>, <тар> и т. д., см, 9 16.2. Стандартные контейнеры и их основные операции разрабатывались так, чтобы обеспечить единство записи и обозначений.
Более того, смысл одноименных операций одинаков для различных контейнеров. Основные операции применимы к любому типу контейнера. Например, ризй баси 6 можно использовать (с разумной эффек- оес1ог<Т> 1(з(< Т> уиеие< Т> з(асй<Т> с(ение< Т> рг(ог(гу диеие<Т зет<Т тиИзе1<Т вектор переменного размера 8 16.3) двусвязный список (9 17.2.2) очередь (9 17.3.2) стек Я 17.3.1) очередь с двумя концами (9 17.2.3) очередь, отсортированная па значению (9 17.3.3) множество (9 17.4.3) множество, в котором одно значение может встречаться несколько раз (6 17А.4) ассоциативный массив (6 17.4.
1) ассоциативный массив, в котором ключ (Кеу) может встречаться несколько раз (9 17А.2) 93 3.8. Алгоритмы тивностыо) для добавления элемента в конец контейнеров и тица оес1ог, и типа !!з1. Каждый контейнер имеет функцию-член з!ге (), которая возвращает количество элементов в нем.
Это единство обозначений и смысла позволяет программистам создавать новые типы контейнеров, которые можно использовать практически также, как и стандартные. Примером может служить тип 1гес с проверкой диапазона (9 3.7.2). В главе 17 демонстрируется, как добавить к библиотеке Ьазй тар (хешируемый ассоциативный массив). Единство интерфейсов контейнеров также позволяет разрабатывать алгоритмы независимо от конкретных типов контейнеров. 3.8.
Рлгоритьлы Такие структуры данных, как список или вектор, сами по себе не представляют большого интереса. Для нх использования нужны базовые операции доступа, такие как добавление и удаление элементов Объекты редко просто хранятся в контейнере. Они сортируются, печатаются, удаляются; извлекаются подмножества элементов контейнера, ищутся вхождения элементов и т.
д. 11оэтому в стандартной библиотеке, наряду с самыми общеупотребительными контейнерами, имеются также и общие алгоритмы нх обработки. Например, следующий пример сортирует вектор и помещает все уникальные элементы вектора в список: ооЫз" (оес1ог< Еп1гу> й ое, Из1< Ел1гу»й !е) ( зог1 (ое,Ьеут (), эе.ел<! ()); ил!уие сору (ое.Ьеу!и (), ое.елд (), !е,Ьеу!и ()); Стандартные алгоритмы описываются в главе 18. Они выражаются в терминах последовательностей элементов Ц 2.7.2).
Последовательность представлена парой итераторов, указывающих на первый элемент и <элемент, следующий за последним»< В нашем примере зог1() сортирует последовательность, начиная с ве.Ьед!л () по ое.еле! (), то есть все элементы вектора. Для записи вам необходимо задать только первый элемент, который должесс быть записан. Если записывается более одного элемента, элементы, следующие за начальным, будут перезаписаны.