Битовый массив
- Войдите на сайт для отправки комментариев
По следам давних выступлений ЕвгенияП
Взял класс битового массива, описанный Евгением вот тут
Если кратко - это структура, содержащая упакованное битовое поле, для которой перегружен оператор индекса [] позволяющий обращатся к битовому полю как к массиву.
Немного переделал под свои нужды - упаковал в байты по 4 двух-битных значения, убрал шаблон. В принципе все получилось и работает. Но у меня в программе подобных массивов будет много, как локальных, так и глобальных. Поэтому хотелось бы создавать и удалять эти массивы динамически, чтобы иметь возможность конктролировать размер доступной памяти.
Пытаюсь переделать пример Евгения для работы с динамической памятью, написал два рабочих варианта, но оба мне не нравятся.
первый такой
#define ASIZE 15 struct CBoolArray { struct CunningBool { uint8_t& bt, mask; CunningBool(uint8_t& _bt, uint8_t _mask) : bt(_bt), mask(_mask) {} operator uint8_t(void) { return static_cast<uint8_t> ((bt >> mask) & 0x03); } uint8_t operator = (const uint8_t b) { return (bt = (b<<mask) | (bt & (~(0x03 << mask)))); } }; uint8_t anArray[(ASIZE + 3) / 4]; CBoolArray(void) { memset(anArray, 0, ((ASIZE + 3) / 4));} CunningBool operator [] (int n) { return CunningBool(anArray[n / 4], (3 -n % 4)); } };
вроде все ОК, но при попытке создать обьект оператором new к массиву байт приходится обращаться по ссылке, что полностью обесценивает всю изящность решения с перегрузкой оператора:
CBoolArray* bitsArray = new CBoolArray; // some function void boo() { (*bitsArray)[12] = 2; }
другой вариант - создать динамический массив для бит прямо внутри обьекта:
#define ASIZE 15 struct CBoolArray { struct CunningBool { uint8_t& bt, mask; CunningBool(uint8_t& _bt, uint8_t _mask) : bt(_bt), mask(_mask) {} operator uint8_t(void) { return static_cast<uint8_t> ((bt >> mask) & 0x03); } uint8_t operator = (const uint8_t b) { return (bt = (b<<mask) | (bt & (~(0x03 << mask)))); } }; uint8_t* anArray; CBoolArray(void) { anArray = new uint8_t[(ASIZE + 3) / 4]; memset(anArray, 0, ((ASIZE + 3) / 4)); } ~CBoolArray() { delete[] anArray; } CunningBool operator [] (int n) { return CunningBool(anArray[n / 4], (3 -n % 4)); } };
этот вариант тоже рабочий, но эта структура получается не совсем динамическая, да и совершенно впустую расходуется лишние 2 байта на указатель anArray
В чем вопрос... как бы к усам Иван Иваныча приставить бакенбарды Николая Платоныча... то есть типа совместить достоинства двух вариантов. Не могу понять, как создавать такую структуру динамически, не теряя возможности использовать перегруженный индекс напрямую.
99% что всё можно выделить на стеке.
Евгений, не уверен, что перегрузка new мне чем-то поможет. Ведь в любом случае после оператора new я получаю не саму структуру, а ссылку на нее. А значит опять придется обращаться к индексам так:
а хотелось бы так
99% что всё можно выделить на стеке.
Программа работает до исчерпания памяти. При выделении памяти из кучи я могу контроллировать момент окончания памяти и хотя бы корректно завершить работу. При автоматическом выделении переменных на стеке - стек просто наезжает на данные и все крашится без всякой диагностики.
Так надо просто статически заполнить всю память и всё.
Евгений, не уверен, что перегрузка new мне чем-то поможет. Ведь в любом случае после оператора new я получаю не саму структуру, а ссылку на нее. А значит опять придется обращаться к индексам так:
а хотелось бы так
Во, блин! Ну, Вы уж это ... поаккуратнее в выражениях. От Вас-то я не ожидаю, что перепутывания терминов "ссылка" и "указатель", потому и не понимаю ни хрена, что Вы пишете. Только из примера дошло.
Т.е. речь исключительно о "синтаксическом сахаре", чтобы явно не писать разыменование? Так?
Т.е. речь исключительно о "синтаксическом сахаре", чтобы явно не писать разыменование? Так?
да, только о нем
это вы зря... :) Я хотя и понимаю разницу, но хронически путаю эти термины в разговоре :)
Хотя в данном случае... что не так? Оператор new возвращает указатель на созданный экземпляр обьекта, который (указатель) присваивается ссылочной переменной bitsArray, через которую мы и обращаемся к нашей структуре...
нашел опечатку в первом сообщении
для 4х 2хбитовых значений в байте оператор индекса будет таким
Та ты не переживай, ни кто там не читал даже. Ни один нормальный не полезет в ту хрень чтоб байтовые поля в массиве хранить, а ограничится чем то типа (Arr[n/4]>>(n&3)). Нет смысла усложнять примитивной.
А чем не устраивает стандартное :
Очень много полей ???
Очень много полей ???
от 20 до 60-ти :)
Но главное - чтобы итерировать по ним в цикле. Сейчас используется массив, где каждое значение занимает байт. Хочу уменьшить размер в 4 раза, ибо таких массивов много.
Вопрос экономии места чисто спортивный :) - это сразу чтоб не обсуждать зря, нужно мне это или нет. :)
Можно было бы ссылку сколхозить, но, зараза, битовый массив не имеет адреса.