Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 145
Текст из файла (страница 145)
Символы имели определяемых пользователем операций копирования. Это также способствует эффективному и простому вводу/выводу строк. Свойства символьного типа представляются с помошью специализаций шаблона сйаг <га!<к <етр(а<е<с(аюз СЬ> ю(гис( сйаг <га(<ю ( ) ( определенного в пространстве имен яь<. Сам по себе он мапо интересен, так как применяются его специализации для конкретных типов символов. Рассмотрим сйаг (га(гю<сйаг>: <етр(а1е<> ю<гис< сваг (гай<сйаг> ( (уре((е2 сйаг сйаг 1уре; ю<айс ио(а аюю(ап (сйаг (урез, солю< сйаг <урез); УУ тил символа УУ = для сйаг <уре УУ числовое представление символов: (уре((еу т< (п( (уре; У тип целого для символов ю(а(!с сйаг 1уре <о сЬаг <уре(сот< т( (урез) ( УУ !и( (о сйаг сопке(лоп ю(айс ип <уре <о <п( 1уре (солт сйаг <урез) ( УУ сйаг 1о !л( солчегю(оп манойло!е(( и(( <уре(сот< 1п< 0(рею, соимт( 0(рею); У== !сравнения для сйаг <уре: заабс Ьоо( ец(сопз(сйаг (урез, сои<а сваг (урез) ( з<аис ьоо! 1<(соим сйаг (урез, солю! сйаг <урез) ( уу == уу < УУ операции над массивами з(л(( ю<а<<с сйаг (уре* тоге(сйаг (уре* ю, сопя( сйаг <уре* (2, ю!зе < и); я<а<(с сйаг <уре* сору(сйаг <уре' ю, сопя< сйаг <уре* (2, ю<яе < и) ( ю(а((с сйаг <уре* а(я<ел(сйаг 1уре* ю, ю(ге 1и, сйаг 1уре а); з<аис и(< сотраге (солю< сьаг <уре* ю, соню< сьаг (уре* ю2, ю!ге < и ); та<!с ю((е < !ела(Ь (сот< сйа( 1уре* ); <аа(к солю(сйаг <уре* ((л(((солю< сйаг (уре* з, (и< и, сопя< сйаг <урез) ( У(все, что связано с 1(0( <уре((е! я<сеато(2 оЯ <уре( <уре((е(' <агеатрою роз <уре( <уре((ея тйю(а(е 1 ю<а<е <уре( У смен(ение в потоке У позиция в потоке УУ состояние мультибайтного потока УУ ел((-оЯйе (конец файла) У( 1, если только ( неравно ео2[) я<або (п( 1уре еоу ( ) ( найс ии 1уре по( ео('(солю( 1п( <урез 1) ( таис ю(а1е <уре ае< ю<а(е (рою (уре р) ( )( Реализация стандартного строкового шаблона, Ьая(с ю<г(иа Я20.3), опирается на определенные здесь типы и функции.
Тип, применяемый Ьая!с вития в качестве типа символов, должен поддерживать эти типы и функции. Чтобы символьный тип был сйаг <уре, должен иметься способ получения целочисленных значений для каждого символа. Тип этого целого — 1и( (уре, а преобразования от этого типа к сйа( (уре и обратно выполняются функциями <о айаг <уре() и <о (л< гуре () . Для сйаг эти преобразования тривиальны. Как (иоие(я, я2, и), так и сору(ю, ю2, и) используют вызов аяя<яи (ю [(), я2[() ), чтобы скопировать и символов из я2 в я. Разница состоит в том, что тозе() работает 692 Глава 20 Строки корректно, даже если [зз»п [ и [з2з2»п[ перекрываются.
Из-за этого сору() может оказаться быстрее. Это все напоминает ситуацию с функциями тетсру() и теттоге() из библиотеки языка С (519.4.6). Вызов аяз[дп(з,п,х) присваивает и значений х строке з при помощи аяз[яп(я [!1,х) . Функция сотраге() использует а() и еа() для сравнения символов. Ее возврат имеет тип зпз, причем нуль означает точное совпадение; отрицательное значение свидетельствует о том, что первый аргумент лексикографически предшествует второму, а положительное — что второй предшествует первому. Такой возврат аналогичен возврату функции з(гетр() (520.4.!) из библиотеки языка С.
Функции, имеющие отношение к вводу/выводу, используются реализациями низкоуровневых средств ввода/вывода 521.6.4). «Широкие» символы — то есть объекты типа псЬаг 1 Я4.3), похожи на символы типа сйаг, но требуют двух или более байт. Свойства псйаг 1 описываются специализацией сЬаг зга[зз<псЬаг з>: гетр!а(е<> ззгасз сааг (гааз <псааг г> ( Зурейе/пСЬаг З слог (уре; Зурейег пйпз З зпг гуре; Зурейе/пзггеатоЯ оЯ гуре; зурейе/' и язгеатроз роя гуре; ~У как сЬаг (гацз<слаг> )' Тип псЬаг г используется для хранения 16-битных символьных наборов, таких как (3п[сог[е. При этом нззгеатроз может отличаться от ззгеатроз, так как может понадобиться хранить состояние смещения [з))[[) з(а(е) [в[3.4.6).
20.3. Стандартный строковый шаблон Ьаыс ь~плд Строковые средства стандартной библиотеки базируются на шаблоне Ьаз[с ззг[пд, предоставляющим типы данных и операции аналогично стандартным библиотечным контейнерам (516.3): зетр1а<е<с1азз СЬ, с(ат Тг = слог зга[зз<СЬ>, с1азз А = айосазог<СЬ» с1азз ззй:: Ьазгс ззг(пд ( риЬДс: ~У ... ) Этот шаблон определен в пространстве имен мй и расположен в заголовочном файле <ззг[пя>. С помощью следующих операторов гурейе/'задаются общепринятые имена для строковых типов: зурейеу Ьазйс ззггпд<сЬаг> ззггпд; Зурейе1 Ьазгс згг1пд<пслаг 1> пзайпд; Тип Ьаз[с ззг)пд похож на гесгог [916.3), но вместо операций, типичных для списков, он определяет операции, типичные для строк, такие как поиск подстрок.
Реа- 20.3. Стандартный строковый шаблон Ьаз)с з1()по 693 лизация Ьаяс злтля с помошью чес<ог или простого массива маповероятна. Типичные строковые операции эффективнее выполняются реализациями, которые минимизируют копирование, не выделяют каждый раз динамическую память под короткие строки, допускают простые модификации длинных строк и т.д. 1см. 620.6]12]). Большое количество функций подчеркивает особую роль строкового типа, а также тот факт, что некоторые платформы могут предоставлять аппаратную поддержку строковым операциям.
Разработчику библиотеки легче применить аппаратную поддержку, если объявлена стандартная функция со схожей семантикой. Как и другие стандартные библиотечные типы, Ьаяс зптля<Т> является конкретным типом 162.5.3, 610.3) без виртуальных функций. Можно использовать члены такого типа в качестве полей более изошренных классов, предназначенных для реализации специализированных строк, но он не предназначен лля использования в качестве базового класса 525.2.1) см. также 520.6[10]).
20.3.1. Типы Как и чес<ог, Ьаяс зл 1лл определяет связанные с ним типы с помощью оператора 0рейеу. <етр<а<е<с<азз СЬ, с<азз Тг = сааг <га<<з<СЬ>, с(азз А = адоса<ог<СЬ» с1азз Ьаз<с з<гйпк 1 риЫ<с: << типв< !похоже на чес<ог, !<з< и тд.: З! бЗ. 1)< <урейе) Тг <го<уз 1уре; ~У спе<(ифично для Ьаяс лилля <урейеТ<урепате Тг: < сваг (уре ча(ие <уре< ~рейеТА а1!оса<ог <уре< (урейеТ1урепате А: <в<хе <уре яге <уре< (урейеу <урепате А: < йфегепсе <уре й<ТТегепсе <уре; (урейеТ(урепате А:: геГегелсе геТегепсе; урейеТ<урепатеА::солз< ге~егепсе сопл< гегегепсе< (урейеГ<урепате А:: ро!п<ег ро<п(ег; <урейез'(урелате А <: сопл<роги<ее сопяро<злег; <урейе!' <тр<етел(а<<оп йе!)лей 1<его<о<< <урейе1 <тр<етеп<а<<оп йеЯпей сопл< дега(ог< <урейерз<й::гечегзе Йега1ог<де<а<ог> гечегзе йега1ог; <урейерз<й: <гечегзе Лега<ог<сопт Ьега<ог> сопЯ тече<хе дега<о<э <У...
Класс Ьаз!с злтлл поддерживает строки символов разных типов, а не только строки Ьаяс апля<сйаг>, известные как злтля. Например: <урейе!'Ьаз1с в<<<ля<лаз<алей сааг> СЪ<г<лл< ягис(зсааг 1 !* ... *l ); Утин для японских сил<волов <урейе3' Ьаяс в<пад <лола<> Хяппд < Строки таких символов могут использоваться точно так же, как строки символов типа сЬаг, до,тех пор, пока позволяет семантика символьного типа. Например: Глава 20. Строки 694 г/и<г(пд()ги( гО( .< ии(г(пля ( бз(г!лО:: и!ге (уре роз = из.Яп<(( ' ' ); гегагп !/и(г!пО (ии, О,рои) < ) //см. 320.3.!! //см.
~20.3.4 Ли(г(пд (<ги( то(<( (сопз( Лз(г(пдь /и) ( ии(г(пО <: и((е (уре роя = !и . Япд ( ' ' ) ( ге<игл уи(г!пО ((и, О, роз) ( //см. 320.3.!! //см. 320.3.4 Естественно, можно использовать шаблоны, принимающие строки в качестве параметров шаблона; (етр(а(е<с1азз Я> $3<ги( лог(((сопи( Яя з) ( <урелате Я::и(ие (уре роз = з.!)п<((' ' ) ( //см. 3203!! ге<игл Я(з, О,роз) < //см. 420.3.4 ) 20.3.2. Итераторы Как и другие контейнеры, и(г(пя предоставляет итераторы (в том числе и обратные): <етр!а(е<с1аии СЬ, с(аяз Тг= сваг (га!уз<СЬ>, с(азз А = а(!оса(ог<СЬ» с!ат Ьаис и(г!пО ( риЫ1с: // ...
// итераторы (как у чес(ог, 1и( и т.д.< я!6.3.2!( аега(о( Ьед(п () ( сопи( аега<ог Ьед!п () соли<( ((ега(ог елО (); соли< иега(ог еп<(() соли!; сече(ее 1(ега<ог гЬе8(л (); соли< гечегзе 1<ега<ог гЬеО!п () солт( гечегие <(ега(ог гелО () ( соли( гечегзе !<его<о( гелй() сопи<( // ... Поскольку и(г1ля определяет необходимые типы и имеет функции, возврашаюшие итераторы, этот тип можно использовать со стандартными алгоритмами ~глава 18). Например: Объекты типа Ьаи(с иптпя< СЬ> могут содержать любые символы из набора СЬ. В частности, строки типа и(г(пя могут содержать нуль.
Символьный тип СЬ обязан вести себя так, как ведут себя символы. В частности, он не должен иметь определенных пользователем копирующего конструктора, деструктора и операции присваивания. 20.3. Стандартный строковый шаблон ))аз[с згг[пй 699 гогй Т(в!с!иль в) вгггпк:: вега! ог р =Япд (в . Ьее[п ( ), в . еид ( ), ' а ' ) ! ~У ... ) Но наиболее типичные для строк операции класс вв !ии предоставляет сам. Можно надеяться, что эти методы оптимизируются сильнее, чем это возможно для универсальных алгоритмов.
Стандартные алгоритмы (глава 18) вообще для строк не столь полезны, как можно бьшо бы подумать. Дело в том, что стандартные алгоритмы полагают отдельные элементы контейнеров значимыми в изоляции от других элементов. Для строк же важна именно последовательность следования ее элементов (символов). Поэтому, сортировка универсальных контейнеров улучшает условия их использования, а сортировка строк просто портит их (изменение порядка следования элементов строки лишает ее смысла). Итераторы для вгг!пя не осуществляют проверку диапазона.