Как сохранить бит-массив в С++?

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

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

Также:

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

Ответ 1

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

Ответ 2

a char, а затем маскирование на 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);
}

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

Ответ 3

Для ванильного С++, std:: bitset.

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

Мэтт Аустерн хорошая статья об использовании.

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

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

Ответ 4

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

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

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

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

vector:: iterator myItr = myVector.begin()

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

Например

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

Ответ 5

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