Как сохранить битовый массив в C++?

Как лучше всего хранить битовый массив в C++ (без Boost, только стандартные контейнеры), представляя, например, растровое изображение распределения томов?

Я думал std::vector<bool> отличная идея, но видимо, это зло и deprecated, так есть ли лучший выбор?

также:

Если у меня есть массив байтов в памяти, как я могу скопировать их в рекомендуемый контейнер?
(У меня возникли проблемы с выяснением этого для vector<bool>.)

5 ответов


массив символов, а затем маскировка 0x1 будет действовать как битовый массив.

пример:

char bitarray[4]; // since 4*8 this array actually contains 32 bits

char getBit(int index) {
    return (bitarray[index/8] >> 7-(index & 0x7)) & 0x1;
}

void setBit(int index, int value) {
    bitarray[index/8] = bitarray[index/8] | (value & 0x1) << 7-(index & 0x7);
}

конечно, эти операции обычно сравнительно медленные, но если проблема с памятью, это достойный способ пойти. Я выбрал Чара для этого, чтобы уменьшить количество необходимых смен. Однако это все еще может быть быстрее с целыми числами.


просто разместив это 6 лет спустя для потомков: как сказал один из комментаторов, я пришел к выводу, что это прекрасно использовать std::vector<bool> Как свой собственный специализированный тип. Единственное, что вам нужно быть осторожным, это не относиться к нему как к стандарту bool контейнера, так как это не так.


для vanilla C++ есть std:: bitset.

Bitset очень похож на vector (также известный как bit_vector): он содержит коллекцию битов и обеспечивает постоянный доступ к каждый бит. Существует два основных различия между bitset и вектор. Во-первых, размер набора не может быть изменен: bitset параметр шаблона N, который указывает количество битов в bitset, должна быть целочисленной константой. Во-вторых, bitset не является последовательностью; в фактически, это вообще не контейнер STL.

Мэтт Austern имеет хорошая статья о его использовании.

и: Если ваш байтовый массив (bit array?) вписывается в unsigned long, затем вы можете назначить его std:: bitset напрямую:

unsigned long myByteArray = 0xABCD;
std::bitset<32> bitten( myByteArray );

Я думаю, что некоторые из пунктов, сделанных на сайте, с которым вы связаны, кстати, не верны. Почти на каждом компьютере размер бита действительно один байт (такой же, как символ), потому что компьютеры могут адресовать только байт не бит в байте (если бы вы могли, тогда у вас была бы только одна восьмая адресного пространства, которое у вас есть в настоящее время с байтами)

Я бы просто использовал байт для вашего вектора, потому что он дает другим людям, которые читают ваш код, лучшее представление о следе памяти ваше приложение.

ОЗУ очень много на современных компьютерах, поэтому вы можете использовать большие интегральные типы, но реально вы не можете идти меньше байта.

для копирования данных из одного контейнера в другой сначала создайте итератор для контейнера

вектор:: итератор myItr = myVector.begin ()

и повторите вектор с циклом while или циклом for, пока myItr не достигнет myVector.конец.)(

для пример

for(vector<bool>::iterator myItr = myVector.begin(); myItr<myVector.end(); ++myItr)
{
   otherContainer.append(*myItr);
}

на std:: bitset будет делать, пока ваш битовый массив фиксированного размера.
В качестве примечания есть также std:: dynamic_bitset, но я не уверен на 100%, что он попал в стандарт.