|
Программирование >> Разработка устойчивых систем
Чак Эллисон (Chuck Allison) спроектировал и разработал исходные эталонные реализации bitset и bitstring (предшественника vector<bool>) во время своей активной работы в комитете по стандартизации C++ в середине 1990-х годов. назначены для выполнения операций с группами двоичных флагов. Основных различий между этими типами два. Битовое поле (bitset) содержит фиксированное количество битов. Количество битов задается в аргументе шаблона bitset. Класс vector<bool>, как и обычный вектор, расширяется динамически и позволяет хранить любое количество элементов типа bool. Шаблон bitset проектировался специально для достижения максимального быстродействия при операциях с битами и не принадлежит к числу обычных контейнеров STL. Из-за этого он не поддерживает итераторы. Размер поля в битах, передаваемый в параметре шаблона, известен на стадии компиляции, благодаря чему базовый целочисленный массив может храниться в стеке времени выполнения. С другой стороны, контейнер vector<bool> является специализацией класса vector и поддерживает все операции обычного вектора - просто эта специализация рассчитана на эффективное хранение данных типа bool. Тривиальное преобразование между типами bitset и vector<bool> невозможно. Отсюда можно сделать вывод, что эти два контейнера предназначены для разных целей. Более того, ни один из них не является традиционным контейнером STL . Шаблон bitset обладает собственным интерфейсом для работы с отдельными битами и не имеет ничего обшего с рассмотренными контейнерами STL. Специализация вектора vector<bool> похожа на контейнер STL, но ведет себя несколько иначе. Эти отличия будут рассматриваться далее. Контейнер bitset<n> в аргументе шаблона bitset передается беззнаковое целое число - количество битов в поле. Следовательно, bitset<10> и bitset<20> являются разными типами, поэтому между ними не могут вьшолняться операции сравнения, присваивания и т. д. Битовые поля обеспечивают выполнение основных поразрядных операций в наиболее эффективной форме. Однако во внутренней реализации bitset биты логически упаковываются в массив с целочисленными элементами (обычно unsigned long с минимальной длиной 32 бит). Единственное преобразование bitset в число определено только для unsigned long (оно выполняется функцией to ulong()). Следующий пример демонстрирует практически все возможности битовых полей (отсутствующие операции несущественны или тривиальны). Справа от выходных данных каждой операции выводится ее краткое описание, а все биты выровнены так, чтобы их было удобно сравнивать с исходными значениями. Если вы еще недостаточно хорошо разбираетесь в поразрядных операциях, эта программа должна помочь. : C07:BitSet.cpp {-Ьог} Работа с классом bitset #incl ude <bitset> linclude <climits> linclude <cstdlib> linclude <ctime> linclude <cstddef> linclude <iostream> linclude <string> using namespace std: const int SZ = 32: typedef bitset<SZ> BS: template<int bits> bitset<bits> randBitsetO { bitset<bits> rCrandO): forCint i = 0: i < bits/16 - 1: i++) { r = 16: Объединение операцией OR с младшими 16 битами нового значения: г 1= bitset<bits>CrandC)): return г: int mainC) { srand(timeCO)): cout sizeofCbitset<16>) = sizeofCbitset<16>) endl cout sizeof(bitset<32>) = sizeofCbitset<32>) endl cout sizeofCbitset<48>) = sizeofСbitset<48>) endl cout sizeofCbitset<64>) = sizeofСbitset<64>) endl cout sizeof(bitset<65>) = sizeofCbitset<65>) endl BS a(randBitset<SZ>()). b(randBitset<SZ>C)): Преобразование битового поля в число: unsigned long ul = a.to ulongC): cout a endl: Преобразование строки в битовое поле: string cbits( 111011010110111 ): cout as a string = cbits endl: cout BSCcbits) [BSCcbits)] endl: cout BSCcbits. 2) [BSCcbits. 2)] endl: cout BSCcbits. 2. 11) [BSCcbits. 2. 11)] endl: cout a [a] endl cout b [b] endl Поразрядная операция AND: cout Ca & b) [a & b] endl: cout CBSCa) &= b) [a &= b] endl: Поразрядная операция OR: cout Ca I b) [a b] endl: cout CBSCa) 1= b) [a = b] endl: Поразрядная операция исключающего OR: cout Ca * b) [a * b] endl: cout CBSCa) b) [a = b] endl: cout a [a] endl: Для сравнения Логический сдвиг влево Сс заполнением нулями): cout CBSCa) = SZ/2) [а = CSZ/2)] endl: cout (а SZ/2) end!: cout а [а] endl; Для сравнения Логический сдвиг вправо (с заполнением нулями); cout (BS(a) = SZ/2) [а = (SZ/2)] endl; cout (a SZ/2) endl; cout a [a] endl; Для сравнения cout BS(a).set() [a.setO] endl; fordnt 1=0; i < SZ; i++) Ifda.testd)) { cout BS(a).setd) [a.set( 1 )] endl; break; Только одна операция cout BS(a).resetO [a.reset()] endl; fordnt j = 0; j < SZ; j++) 1f(a.test(j)) { cout BS(a).reset(j) [a.reset( j )] endl; break; Только одна операция cout BS(a).flip() [a.fllpO] endl; cout -a [-a] endl; cout a [a] endl; Для сравнения cout BS(a).fl1p(l) [a.flip(l)] endl; BS c; cout с [с] endl; cout c.countО = с.countО endl; cout c.anyO = (C.anyO ? true ; false ) endl; cout c.noneО = (c.noneO ? true ; false ) endl; c[l].fl1p(); c[2].flip(); cout с [с] endl; cout c.countО = с.countО endl; cout C.anyO = (C.anyO ? true ; false ) endl: cout C.noneO = (C.noneO ? true : false ) endl: Индексация: с. resetO; fordnt к = 0: к < c.slzeO: k++) if(k % 2 0) c[k].fl1p(); cout с [с] endl; с. resetO: Присваивание логических значений: fordnt ii = 0: 11 < c.sizeO; ii++) c[1i] - (randO % 100) < 25; cout с [с] endl; Проверка логических значений: if(c[l]) cout c[l] == true : else cout c[l] == false endl: } /;- Чтобы результаты не были слишком однообразными, функция randBitset() генерирует случайные битовые поля. В этой функции оператор сдвигает очеред-
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |