![]() |
Простой пул объектов переменного размера
Часто мы имеем множество объектов одного семантического типа, но разных размеров, к примеру : строки, изображения, геометрия и тд. Предлагаю рассмотреть несколько паттернов которые позволяют упростить организацию, хранение и работу с такими объектами.
Для примеров будем брать хранение изображений в виде raw RGBA по 8 бит на канал. Рассмотрим самый банальный вариант который приходит в голову : Код:
struct image_t Первая оптимизация заключается в самом векторе, представим его так : (malloc для последующих нужд) Код:
size_t count = ...; Как теперь можно поместить данные изображения в этот пул ? самый банальный вариант это просто выделить место под все изображения, первую часть пула использовать как массив структур, а вторую часть пула для данных. В общем такой способ достаточно хорош, но не слишком уж и изящный. Write in C (видео) Изящный подход будет основываться на хаке, который пришел к нам из системного программирования, официально утверждён только в C99, отсутствует в стандартах C++, но его поддерживают большинство современных компиляторов. Он называется flexible array member. Суть в том что мы получаем структуру, с массивом на конце, но мы не указываем его размер. Банально да ? Пример синтаксиса : Код:
struct foo Но все операции работают как и с обычный массивом. К примеру : Код:
foo test; Используя этот подход мы сможем организовать пул с такой схемой расположения в памяти : img_struct, img_data, img_struct, img_data ... Код:
struct image_t Теперь разбор полётов, aka faq. 1) Мне нужен класс, а не структура, нужен конструктор и деструктор. Без проблем, руками вызываем placement new и placement delete. Синтаксис такой : Код:
class foo Если вам нужно постоянно обращатся к элементам переменного размера по индексу то проще всего будет использовать пул где в структуре используется указатель на массив данных (пример с unsigned char * raw, описан выше). Но если данных несколько (к примеру изображение с массивом мип-мапов) то дешевле всего в начало пула поместить массив указателей на структуры изображения в пуле, а сами данные размещать за структурой изображения как описано в этой статье, очевидно что описать все массивы с помощью поля переменного размера не получится, к второму и последующим массивам прийдется рассчитывать указатель руками. Так же возможен немного другой обход указаний по индексу, переделайте свои индексы в указатели, когда данные на диске храните в указателях смещение в пуле (или всё же индекс элемента), а после загрузки пройдитесь по всем элементам и замените индексы на указатели, и во время работы вам не понадобится обращаться к элементам по индексам. 3) А как мне удалять элементы, создавать новые и тд ? Пулы элементов переменного размера в общем не предназначены для динамического изменения. Вам нужно использовать другие структуры, например хип. |
Часовой пояс GMT +4, время: 13:44. |
vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot