Как сохранить бит-массив в С++?
Каков наилучший способ хранения битового массива в С++ (без 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% уверен, что он попал в стандарт.