Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 108
Текст из файла (страница 108)
521 Алгоритмы <а(яогййо»> общие алгоритмы Глава 18 <сгтайй> Ьзеагсй () озогт() 518.1.1 Типичный обобщенный алгоритм может применяться к любому интервалу (последовательности) (83.8, 518.3) контейнерных элементов любого типа. Функции Ьзеагсй () и уогг() из стандартной библиотеки языка С применимы ко встроенным массивам элементов типов, не имеющих копирующих конструкторов и определяемых пользователем деструкторов 57.7). Проверка диагностических утверждений (условий) с генерацией исключений описана в 524.3.7.1. Строки Глава 20 строка элементов Т <зтг(ля> классификация символов <с<туре> классификация символов из расширенного набора функции над строками в стиле С э 20.4.2 э20.4.1 < с»«стуре> < сзгггая> функции над строками «широких» символов в стиле С 920.4 <снсйагр> 920.4.1 функции над строками в стиле С < се(~И(Ь > Заголовочный файл <сзМая> объявляет семейство функций зтг!ел(), заору() и т.д.
Заголовочный файл <сзт««7«Ь> объявляет функции агоу() и агат(), конвертирующие С-строки в числовые значения. Итераторы позволяют реализовать обобщенные алгоритмы, работающие поверх любых стандартных контейнеров и аналогичных объектов (82.7.2, 819.2.! ). Глава 16. Организация библиотеки и контейнеры 522 Ввод/вывод <1ее еаие> шаблон потока ввода 321.3.1 321.3.1 <оеегеаж> ) шаблон потока вывода 321.4.6.2 ) <Йгиаи1р> манипуляторы 821.5.3 потоки ввода/вывода в строки иэ строки <еей еага > 320.4.2 функции для работы с символами <сс1уре> 821.5.1 ) <Геегеаие> потоки ввода/вывода в файлы ) <сеее11о> 321.8 семейство функций рг1иф'() ) <сегсйаг> 821.8 Манипуляторы — это объекты, предназначенные для управления (манипулирования) состоянием потока (например, для изменения формата вывода чисел с плаваюшей запятой) 521.4.6).
Локализация 821.7 представляет локальные особенности <Еоса1е> < с1оса1е> представляет локальные особенности в стиле С 821.7 Заголовочный файл <1оса1е> посвящен локализации отличий в формате дат, символах обозначения валют и критериях сравнения строк, свойственных разным естественным языкам и культурам. Поддержка языка <1ийзе> числовые пределы 822.2.1 322.2.1 816.1.3 динамическое распределение памяти <иеег> <еуре1иГо> поддержка идентификации типов на этапе выполнения <ехсеряои> поддержка обработки исключений э14 10 <сетеЫеу> языковая поддержка библиотеки С 86.2.1 87.6 <сетеЕага> зк18.7 раскрутка стека в стиле С <сзериер> < сеее111Ь > завершение программ <сйиее> системные часы обработка сигналов в стиле С зк18.7 <се1аиа1> <сптийе> <сутоае> ввод/вывод символов иэ расширенного набора в стиле рг)иЕЕ () макросы числовых скалярных пределов в стиле С макросы пределов чисел с плавающей точкой в стиле С поддержка функций с переменым числом аргументов 39.4.1.1 30.4.4.1 16.1.
Проектные решения стандартной библиотеки. Заголовочный файл <сзггЫеу> определяет: тип значений, возвращаемых зггеоу"(), згее г, тип результата вычитания указателей и индексов массива, ргггггК г (86.2.!) и пользующийся дурной репутацией макрос ЖШ 85.1.1). Раскрутка стека в стиле языка С (с использованием зеггтр и!олг(гтр из <сзегутр> ) не совместима с обработкой исключений (88.3, глава 14, приложение Е) и ее лучше избегать. В нашей книге раскрутка стека в стиле языка С и сигналы не рассматриваются, так что ссылка относится к стандарту 180 С++.
<сотугех> комплексные числа < гаьгггау> векторы чисел и опе ( <литенс> обобщенные числов ', <стагв> стандартные матема ( случайныечисла вст <сггаг(Ь> По историческим причинам аЬз() и г(гг() находятся в <стгИЬ>, а не вместе с остальными математическими функциями в <стагЬ>. Пользователь и разработчик конкретной реализации стандартной библиотеки не должны добавлять или изымать объявления из стандартных заголовочных файлов. Также не допустимо изменять содержимое этих файлов посредством макросов и локальных определений Я9.2.3). Любая подобная программа или реализация нарушают требования стандарта, а код использующих эти трюки программ непереносим.
Даже если такие программы и работают сегодня, следующие версии реализации стандартной библиотеки могут нарушить их работу. Не следуйте по этому пути. Чтобы применить какое-либо средство стандартной библиотеки, нужно включить соответствующий заголовочный файл. Самостоятельное написание необходимых объявлений не соответствует стандарту. Дело в том, что некоторые компиляторы оптимизируют код, отталкиваясь от факта включения стандартных заголовочных файлов, в то время как другие предоставляют усовершенствованные версии ее средств в ответ на включение соответствующих заголовочных файлов. В любом случае, пользователи не могут и не должны знать, как именно реагируют конкретные реализации на включение стандартных заголовочных файлов.
В то же время, пользователи могут специализировать вспомогательные шаблоны, такие как з(кар() (816.3.9), под конкретные нужды нестандартных библиотек и пользовательских типов. 16.1.3. Непосредственная поддержка языка С++ Небольшая часть стандартной библиотеки осуществляет непосредственную поддержку языковых средств, без которой программы не смогут запуститься и работать. Библиотечные функции поддержки операций пето и гге!еге обсуждаются в 86.2.6, 810.4.11, 814.4.4 и 815.6; они расположены в заголовочном файле <лего>.
Механизм КТТ1 языка С++ опирается на класс гуре гаго, описанный в 815.4.4, и представленный в заголовочном файле <гурегауо>. Глава 16. Организация библиотеки и контейнеры Стандартные классы исключений рассматриваются в 514.10 и представлены в заголовочных файлах <пезг>, зуре1л!о>, <1оз>, <елсерпоп> и <зЫехсерг>. Запуск программы и ее завершение рассматриваются в 53.2, 59.4 и 510.4.9. 16.2. Дизайн контейнеров 16.2.1. Специализированные контейнеры и итераторы Традиционным гюдходом к реализации векторов и списков является их дизайн в соответствии с предполагаемым использованием: р оптимальный !етр!а!е<сгазз Т> с!азз Уесгог ( риЫгс: екр!гсй Уесгог(з1се гп); гУ инициализация п объектами со значением Т() гУ индексация Та орегагог[] (з(ге 1) // ... гетр(а!е<с1азз Т> с(азз Ейг ( рии!с: с(азз Е(пй ( /* ... */ ); // оптимальный Е/з! (); го!а риз (Т*); Т* де!(); р...
// первоначально пустой У поместить перед текущим элементом // получить текущий элемент Каждый класс определяет операции, оптимальные для них самих, а в реализации операций для каждого класса мы можем выбрать любое подходящее представление, не беспокоясь об иных типах контейнеров. Это позволяет выполнить наиболее эффективную реализацию этих операций. К тому же, наиболее употребительные для Контейнер — это объект, содержащий другие объекты. Примерами служат списки, вектора и ассоциативные массивы. В общем случае, объекты можно добавлять в контейнер и удалять их из него. Естественно, столь общая идея может быть представлена пользователям по-разному.
В этом отношении дизайн стандартной библиотеки языка С++ преследует две цели: предоставить максимальную свободу в реализации индивидуальных контейнеров, но обеспечить общий согласованный интерфейс к ним для пользователей. Это помогает оптимизировать код контейнеров при том, что пользовательский код может не зависеть от того, какой конкретный контейнер используется.
Традиционно дизайн контейнеров направлен на то, чтобы отвечать либо первому, либо второму требованию. Контейнерная и алгоритмическая части стандартной библиотеки (часто называемые БТЕ) одновременно обеспечивают и эффективность, и общность. Последующие разделы покажут сильные и слабые стороны традиционного дизайна контейнеров, что поможет лучше понять выбранное для стандартной библиотеки решение. 16.2. Дизайн контейнеров гетр1аге<с1азз Т> с1агв Тгог //общий интерфейс (абстрактный класс з2.5.4, з12.3) ( риЫс: //геен О для индикации состояния «элементов больше нет" //указатель на первый элемент //указатель на следующий элемент Ыггиа( Т*/)гзг() = О; гьы(иа! Т* пехг() = 0; Теперь можно предоставить реализации для векторов и списков: гетр(а<е<с1азз Т> с1аев Ч'есгог дог: риЫ(с 1~ог<Т> //реализация )гес(ог Ресгог<Т>в г; Ясе 1(паек! //индекс текущего элемента риЫгс: нес!о« дог(!'есгог<Т>а»г): г(гг), 1пдех(0) () Т*у)гзг() ( ге!игл (г.ваеО) за»(1пдех=01:0; Т* пехг() ( ге!ига (»«1пдех<г.з!се() )?аг[1пФех):0; ) гетр1аге<сйгзз Т> с(азз ТЫзг дог: риЫ(с 11ог< Тг ( 7лзг<Т»а 1зг! ЙЫ<Т»: ыб(пк р; //реализация /лз( //указывает на текущий элемент риЫ(с: 3.~зг 1(ог (АЫ< Т» а ); Т* У)тг(); Т* пехг(); )' Отобразим это решение графически, применяя пунктирные линии для отображения отношения «реализовано с использованиемгн списков и векторов операции, такие как риг() и орегагог(1 () соответственно, невелики по объему и легко допускают встраивание кода.
Типичная работа с контейнерами любых видов состоит в проходе по всем их элементам (просмотр элементов одного за другим). Обычно это делается путем определения класса итератора, подходящего для данного типа контейнера [см. ~11.5 и $11.14[7[). Однако пользователю, осуществляющему итерацию по элементам, часто нет дела до того, в каком именно контейнере они содержатся — в списке или векторе.