Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 122
Текст из файла (страница 122)
Он оптимизирован для использования в качестве строки символов н в типичном случае используется не так, как стандартные контейнеры. 17.5.2. Массивы зга!аггау Массив га!аггау (522.4) — это вектор, оптимизированный для вычислений. Он не претендует на то, чтобы быть универсальным контейнером. Тип га!аггау предоставляет множество полезных численных операций, однако из стандартных контейнерных операций (917.1.!) он предлагает только яге!1 и операцию индексации (822.4.2).
Указатель на элемент массива га!аггау является итератором произвольного доступа ($19.2.1). 17.5.3. Битовые поля Ь!1яет Часто некоторые аспекты системы, например, состояние входного потока (82!.3.3), представляются в виде набора флагов, отражающих такие бинарные атрибуты, как «хорошо/плохо», «истина/ложь» или «включено/выключено». Язык С++ эффективно поддерживает концепцию небольших наборов признаков (флагов) через битовые операции над целыми числами (86.2.4). К этим операциям относятся ь (побитовое логическое «И»), ~ (побитовое логическое «ИЛИ»), " (побитовое «исключающее ИЛИ»), «(сдвиг влево) и» (сдвиг вправо). Класс Ьбвег<Ж> обобщает эту концепцию и обеспечивает удобную работу с набором из /»Гбит, индексируемых от 0 до /тг-1, где Ж предоставляется во время компиляции.
Для битовых наборов, не помещающихся в иазгаае«(!оаа и», использовать Ьбвег намного удобнее, чем непосредственно целые числа. Для небольших наборов битов с точки зрения эффективности возможны варианты. Если же вы хотите именовать биты, а не нумеровать их, то альтернативой будет применение контейнера агар (517.4.1), контейнера хсг (817.4.3), перечислений (84.8) или полей битов в структурах (9С.8.1). Класс Ьйвег<Ю> — это массив из Мбит.
От отличается от гесгог<Ьоог> (916.3.11) тем, что имеет фиксированный размер; от лег 8! 7 4 3) — тем, что его биты индексируются целыми числами, а не ассоциируются со значениями; от обоих указанных контейнеров тем, что предоставляет операции для манипуляций с битами. Так как невозможно адресовать отдельный бит непосредственно с помощью встроенного указателя (85.1), Ьйвег вводит тип, ссылающийся на биты. Это универсальная технология адресации объектов, для которых применение встроенных указателей по той или иной причине не подходит: Глава 17. Стандартные контейнеры 590 (етр1а(е<я(ге ( )ч> с(аяя я(а:: Ь(уяе( ( риЫ(с: с1аяя ге7егепсе ( 7г(еп(( с(аяя Ь(еяе(( герегепсе ( ); //ссылка на одиночный бит: // ЬД ссылается на 1(ч-!Рй бит: риЬпс: -ге~егеисе() ( ге/егепсеь орега(ог= (Ьоо! к) ( ге~егепсея орега(ог= (соим ге~егепсеа ) ( Ьоо! орега(ог- () соим; орега(ог Ьоо(() сопи; ге~егепсео.Я(р () ( )( // ...
)( У для ЬЯ = х; //д Ь|(7 = ЬИ: У возврои(аел( -ЬЯ Ф для х = Ь('(/; У ЬЯ,()(р!)( позиция: 9 8 7 6 5 4 3 2 1 0 Ьйея<10>(989). 17.5.3.1. Конструкторы Битовые поля могут конструироваться с умолчательными значениями, из битов чисел типа ипя(япе(1 !оия 1и(, или из строк типа я(г)пя: (етрй((е<я(се ( )ч> с!аяя В!ме( ( риЬИс: р.,, р конструкторы: Ь((яе(() ( Р )(( нулевых бит Ь(уяе( (ипя(еле(( (опе га1); Р боты из оо! (етр(а(е<с1аяя СЬ, с1аяя Тг, с1ат А> У Тг - слагас(ег (гап Я20.2! ехр!1<1( Ь(те((сопя( Ьамс мг(пя<СЬ, Тг, А>я мг, У биты из яо ~релате Ьамс я(ггля<СЬ, Тг, А>::я!яе (уре роя = О, (урелате Ьамс я(г(ив< СЬ, Тг, А>:: я(яе (уре л=Ьаядз я(г!ля<СЬ, Тг, А>:: проз); // ... Шаблон Ь1(яе! определен в пространстве имен м(1 и расположен в заголовочном файле <Ь1(яег>. По историческим причинам Ь1(яе( отличается от других классов стандартной библиотеки по стилю.
Например, если индекс (известный как битовая позиция — Ь1! ромбоп) выходит за штатные границы, генерируется исключение ои! о7' капле. Никаких итераторов для него нет. Битовые позиции отсчитываются справа налево (как нумеруются разряды чисел), так что величина Ь (() равна ро(г (2, () . Таким образом, битовые поля можно трактовать как двоичные числа из )Убит: 591 ) 7.5.
«Почти контейнеры» //! О!О! 01 0! 010! 010 У 00000000000000001010101010101010 Ьйзез<16> 02 = Охаааа| Ьйзег<32> ЬЗ = Охаааа! Ьйзе|<10> Ь4 (зизпВ ("1010101010" ) ) | д 10!0101010 Ьдзя<10> Ь5(зи(пВ ("10110111011110" ), 4) | У О!1101!110 Ь!яя<10> Ьб(захид ( "10110111011110"), 2, В); д 00!10!1101 Ызя<10> Ь7(зпзпВ ("иОВООат) ) | д(ига!(|! огдитеи( (недопустимый аргумент) Ь(зля<10> ЬВ = з|ппВ ( "пОВОО|1" ) | д еггог: нет приведения из зотпВ в Ыяе| сог|гегяоп ) Ключевая идея, с которой спроектирован Ь(гзег, заключается в возможности предоставления оптимизированной реализации для случаев, когда набор битов умещается в одно машинное слово.
Интерфейс отражает такое допущение. 1 г.5.3.2. Побитовые операции Шаблон Ь(гзег предоставляет битовые операции для доступа к отдельным битам и для манипуляции всеми битами в наборе: гетр(азе<з(ге | )«'> с1азз в|4 |: Ь(сзег ( риЬОс: д... д битовые операци|с ге(егепсе орепиог [) (яге | роз); д Ь( 1) Ы(лезь орега|огь= (сопя| Ьйзе|ь з); //апа| (И) Ьйзяь орега|ог( = (сопя Ь|яе|ь з) | до|" (ИЛИ) Ь|яе|ь орега1ог*= (сои|| Ь(теть з) | д ехс1из(ие ог (Ио«ЛЮЧАЮЩЕЕ ИЛИ) Ьйзе|ь орега|ог«= (яге | и] 1 д сдвиг влево (с заполнением нулями) Ьйзе|ь орегагог»= (з(ге | и) | У сдвиг вправо (с заполнением нулями) Ыяегь зе|() ! д установка всех битов в ! Ь|яе|ь ее|(яге |роз, |п| га1= 1) | //Ь(роз(гза! Ьг|ве|ь геке| (); дустановка всех битов в Р Ьйзе|ь геле|(з(зе |роз); д Ь(роз) =О Ьйзегь 111р ( ) д изменение значения каждого бита Ьйзегь (!(р(з(ге | роз) | д изменяет значение Ь(роз) Ь«яе| орега|ог- () сопз| (ге|игл Ьйзег<М> (*!ля) .Яр() | ) //дополнительные биты Ьйзе| орега|ог« (яге | и) сопл| (ге|игл Ьйзег<)Ч> (*|Ыз) «=и; ) д сдвинутые биты Умолчательное значение бита равно О.
Когда задается аргумент типа ипз(ииез( !оиВ |пг, каждый бит этого числа используется для инициализации соответствующего бита в битовом поле (если таковой есть). То же самое делает и Ьаяс зитпВ (глава 20), у которого символ ' О' дает битовое значение О, символ ' 1' дает битовое значение 1, а все остальные символы приводят к генерации исключения 1ига11|1 агдиизеиг. По умолчанию вся строка используется для инициализации. Однако в конструкторах Ьаяс яттиВ (520.3.4) можно указать диапазон используемых символов (от роз до конца символов или от роз до роз+и). Например: го1«()'( ) ( Ьйзя<10> Ы( //все 0 Глава 17.
Стандартные контейнеры 992 Ь(ье< орега<ог» (иге 1 п) сов(( (ге<ига Ь<ье(<М> (*<Ьь]»=п( ) У сдвинутые бтпы // ... )< Операция индексирования генерирует исключение ои( о1 галде, когда индекс выходит за границы набора битов.
Индексации без проверки индекса нет. У этих операций возврат Ь(ье(ь — это *(Ьь. Операции, возвращающие Ыье((а не Ы(зе(а), делают копию *(Ьь, выполняют операцию над копией и возвращают результат. Здесь «и» есть операции битового сдвига, а не операции ввода/вывода. Операция вывода для Ь(ье( есть «, принимающая аргументы типа озьеап( и Ыье( ($17.5.3.3). При сдвиге битов применяется логический (а не циклический) сдвиг. Это означает, что некоторые биты пропадают на конце, а часть битов заполняется умолчательными нулями. Поскольку з(ее (есть беззнаковый тип, то невозможно выполнить сдвиг на отрицательное число, и выражение Ь«-1 на самом деле означает сдвиг на очень большое положительное число. Это фактически обнуляет все биты Ь.
Желательно, чтобы компилятор выдавал в таких случаях предупреждение. 17.Б.З.З. Прочие операции Шаблон Ьйзе(поддерживает такие стандартные операции, как зье О, ==, 1/ О и т пг <етр!а<е<з(ге < )ч> с(азз Ь(ье( ( риЫ!с: ,У... ипз(дне<(!Опй (о и<вид ( ) сопл< ' <етр!а(е <с1азз СЬ, сйьз Тг, с<аззА> Ьа<йс з<г(щ<СЬ, Тг,А> <о з(г<пя() сопл(< <йге 1 сои п1 ( ) соп(1; з(ге (з!ге() сопз< (ге(игп )т( ) // число бит со значением ! У число бит Ьоо( орега<ог== (сопи Ь!<зе(а з) сопл<; Ьоо! орега<ог! = (сопз( Ь(ьеп з) сопи< //(гие если Ь[роз] равно ! // оие если любой бит равен 1 // (гие если никакой бит не равен 1 Ьоо<(ез<(з(ге (роз) соп(1; Ьоо1 апу () сопл<; Ьоо1попе() сопл<< ) Функции (о и!опя() и (о з(ги(я() предоставляют операции, обратные конструированию.
Такие именованные функции были выбраны вместо стандартных операций преобразования, чтобы избежать возникновения неочевидных преобразований. Если значение Ы(зе( имеет так много значащих битов, что его невозможно представить в вице ипз(Ьие(( 1оп», то операция (о и!опд О генерирует исключение оке(7!он ег(ог. Операция (о зь(щ() производит строку выбранного типа, содержащую символы 'О' и '1'; Ьаяс з(г(пя — это шаблон, используемый для реализации строк (глава 20). Операцию (о з(г1пя() можно использовать, например, для генерации бинарного представления целых чисел: 595 ) 7 5. «Почти контейнеры» еоЫ Ыпагу ( ии 1) ( Ь<<ят<В*я<зеоТ((л<) > Ь = 11 У полагаем 8-ЬЬ Ьу<е (см.
также 822.2! сои<«Ь.<о з<пп8<сааг, сваг <гаая<сааг>, авоса<ог<слаг» () « ' ~~и'; ) К сожалению, вызов явно квалифицнруемых шаблонных функций-членов требует редкого синтаксиса (ЗС.[3.6). Еще Ыье< перегружает бинарные операции а, ),, а также обычные операции ввода/вывода: <етр1а<е<я(ее 1]з> Ь1<зе<<Ж> зИ::орска<ось (соля< Ь(<за<<К>я, сот< Ыье<<)Ч>з) 1 <етр<а<е<ше <]у> ы<яе«х> яа<:прего<ос) (сопя< ь(<яе«х>ь, сот< ь<<зе<<х>я); <етр<а<е<з<ее 1]у> Ыье«)Ч> зм«прего<ос*(сопяЫ<яе«гз'>з, сопя< Ы<яе«]»>я) 1 <етр!а1е<с!аяз слагТ, с1азз Тг, я<ее «я<> Ьаис Ь<геат<саагТ, Тг>я я<8: <орега1ог» (Ьазвг Ь<геат<сЬагТ, Тг>а, Ь<<яе<<])<>з); <етр<а<е<с<аяз сьагТ, с1ат Тг, я(зе 1]у> Ьаз<с оягеат<сьагТ, Тг> з за1:: прего<ог« (Ьаяк оз<геат<сьагТ, Тг> з, сот< Ы<ЯЬ<]Я'>З ) 1 Поэтому мы можем вывести битовый набор без преобразования его в строку.
Например: го)8 Ь<пагу (1п< 1) ( Ьияе<<8 я(зеоТ(<л<) > Ь = 1< //полагаем 8-Ьд Ьу<е (см. также 822.2) сои<«Ь « ' ~ п ' < Этот код выводит биты, представляя их символами '(7' и '1' слева направо (старший бит — самый левый). 17.5.4. Встроенные массивы Встроенные массивы обеспечивают индексацию и итераторы с произвольным доступом в виде обычных указателей (92.7.2).