#c #stl #bitset
#c #stl #набор битов
Вопрос:
Из http://www.cplusplus.com/reference/stl/bitset /:
Поскольку в большинстве сред C не существует такого малого элементного типа, доступ к отдельным элементам осуществляется как специальные ссылки, которые имитируют
bool
элементы.
Как именно работает эта ссылка на бит?
Единственный способ, который я мог придумать, это использовать статический массив char
s, но тогда каждому экземпляру нужно было бы хранить свой индекс в массиве. Поскольку каждый ссылочный экземпляр имел бы размер, по крайней мере, a size_t
, это нарушило бы компактность набора битов. Кроме того, изменение размера может быть медленным, и ожидается, что обработка битов будет быстрой.
Ответ №1:
Я думаю, вы путаете две вещи.
bitset
Класс хранит биты в компактных представлениях, например, в char
массиве, обычно по 8 бит на char
(но YMMV на «экзотических» платформах).
bitset::reference
Класс предоставляется для того, чтобы пользователи bitset
класса могли иметь объекты, подобные ссылкам, на биты, хранящиеся в bitset
.
Поскольку обычные указатели и ссылки не обладают достаточной степенью детализации, чтобы указывать на отдельные биты, хранящиеся в bitset
(их минимальная степень детализации — char
), такой класс имитирует семантику ссылки на поддельные операции lvalue, подобные ссылочным, над битами. Это необходимо, в частности, для того, чтобы значение, возвращаемое operator[]
, «нормально» работало как значение lvalue (и это, вероятно, составляет 99% от его «нормального» использования). В этом случае его можно рассматривать как «прокси-объект».
Такое поведение достигается за счет перегрузки оператора присваивания и bool
оператора преобразования в bitset::reference
; bitset
класс, вероятно, будет инкапсулировать ссылку на родительский вр объект и смещение (байты бит) ссылочного бита, которые используются такими операторами для извлечения и сохранения значения бита.
—РЕДАКТИРОВАТЬ—
На самом деле, реализация g позволяет bitset::reference
хранить непосредственно указатель на слово памяти, в котором хранится байт, и номер бита в таком слове. Однако это всего лишь деталь реализации для повышения ее производительности.
Кстати, в библиотечных источниках я нашел очень компактное, но четкое объяснение того, что bitset::reference
такое и что оно делает:
/**
* This encapsulates the concept of a single bit. An instance of this
* class is a proxy for an actual bit; this way the individual bit
* operations are done as faster word-size bitwise instructions.
*
* Most users will never need to use this class directly; conversions
* to and from bool are automatic and should be transparent. Overloaded
* operators help to preserve the illusion.
*
* (On a typical system, this <em>bit %reference</em> is 64
* times the size of an actual bit. Ha.)
*/
Ответ №2:
Я не смотрел на источник STL, но я ожидал бы, что ссылка на набор битов будет содержать указатель на фактический набор битов и разрядное число размера size_t. Ссылки создаются только при попытке получить ссылку на элемент набора битов.
Обычное использование наборов битов вряд ли приведет к широкому использованию ссылок (если вообще приведет), поэтому особых проблем с производительностью возникнуть не должно. И концептуально это похоже на char
типы. Обычно длина символа составляет 8 бит, но для хранения «ссылки» на символ требуется указатель, поэтому обычно 32 или 64 бита.
Ответ №3:
Я никогда не смотрел на ссылочную реализацию, но, очевидно, она должна знать набор битов, на который она ссылается через ссылку, и индекс бита, за изменение которого она отвечает. Затем он может использовать остальную часть интерфейса наборов битов для внесения необходимых изменений. Это может быть довольно эффективным. Обратите внимание, что размер наборов битов нельзя изменить.
Ответ №4:
Я не совсем уверен, о чем вы спрашиваете, но я могу рассказать вам способ доступа к отдельным битам в байте, что, возможно, и делают наборы битов. Имейте в виду, что следующий код не является моим собственным и является спецификацией Microsoft (!).
Создайте структуру как таковую:
struct Byte
{
bool bit1:1;
bool bit2:1;
bool bit3:1;
bool bit4:1;
bool bit5:1;
bool bit6:1;
bool bit7:1;
bool bit8:1;
}
Частью этого кода ‘: 1’ являются битовые поля. http://msdn.microsoft.com/en-us/library/ewwyfdbe (v =против80).aspx
Они определяют, сколько битов должна занимать переменная, поэтому в этой структуре есть 8 bools, которые занимают по 1 биту каждый. Таким образом, в общей сложности структура ‘Byte’ имеет размер 1 байт.
Теперь, если у вас есть байт данных, например, char, вы можете сохранить эти данные в байтовом объекте следующим образом:
char a = 'a';
Byte oneByte;
oneByte = *(Byte*)(amp;a); // Get the address of a (a pointer, basically), cast this
// char* pointer to a Byte*,
// then use the reference operator to store the data that
// this points to in the variable oneByte.
Теперь вы можете получить доступ (и изменять) отдельные биты, обратившись к переменным-членам bool в oneByte. Чтобы снова сохранить измененные данные в символе char, вы можете сделать следующее:
char b;
b = *(char*)(amp;oneByte); // Basically, this is the reverse of what you do to
// store the char in a Byte.
Я попытаюсь найти источник этой техники, чтобы отдать должное там, где это необходимо.
Кроме того, опять же, я не совсем уверен, полезен ли вам этот ответ. Я интерпретировал ваш вопрос как «как будет обрабатываться доступ к отдельным битам внутри?».
Комментарии:
1. Вопрос касается классов
std::bitset
иstd::bitset::reference
стандартной библиотеки C .2. @Matteo Italia: Я это хорошо знаю, я интерпретировал вопрос так, как будто его спросили, как доступ этих классов к битам реализуется внутренне.