К сожалению, обеспечение максимального выравнивания намного сложнее, чем должно быть, и нет никаких гарантированных решений AFAIK. Из блога GotW ( Fast Pimpl article ):
union max_align {
short dummy0;
long dummy1;
double dummy2;
long double dummy3;
void* dummy4;
/*...and pointers to functions, pointers to
member functions, pointers to member data,
pointers to classes, eye of newt, ...*/
};
union {
max_align m;
char x_[sizeofx];
};
Это не гарантируется полностью
портативный, но на практике это близко
достаточно, потому что мало или нет
системы, на которых это не будет работать как
ожидается.
Это о ближайшем "взломе", который я знаю для этого.
Есть еще один подход, который я использовал лично для супер быстрого распределения. Обратите внимание, что это зло, но я работаю в областях трассировки лучей, где скорость является одним из величайших показателей качества, и мы ежедневно профилируем код. Он включает использование распределителя кучи с предварительно выделенной памятью, которая работает как локальный стек (просто увеличивает указатель на выделение и уменьшает указатель на освобождение).
Я использую это для Пупырышки особенно. Однако просто иметь распределитель недостаточно; чтобы такой распределитель работал, мы должны предположить, что память для класса Foo выделена в конструкторе, эта же память также освобождается только в деструкторе, и что сам Foo создается в стеке. Чтобы сделать его безопасным, мне нужна была функция, чтобы увидеть, находится ли указатель 'this' класса в локальном стеке, чтобы определить, можем ли мы использовать наш сверхбыстрый распределитель стека на основе кучи. Для этого нам пришлось исследовать решения для конкретных ОС: я использовал TIB и TEB для Win32 / Win64, а мои коллеги нашли решения для Linux и Mac OS X.
Результатом, после недели исследования методов, специфичных для ОС, для определения диапазона стека, требований к выравниванию и выполнения большого количества тестирования и профилирования, стал распределитель, который мог распределить память за 4 такта в соответствии с нашими тестами счетчиков тиков как в отличие от 400 циклов для нового malloc / оператора (наш тест включал конфликт потоков, поэтому malloc, вероятно, будет немного быстрее, чем это в однопоточных случаях, возможно, пару сотен циклов). Мы добавили стек кучи для каждого потока и обнаружили, какой поток использовался, что увеличило время примерно до 12 циклов, хотя клиент может отслеживать распределитель потоков, чтобы получить распределение по 4 циклам. Это стерло горячие точки на основе распределения памяти с карты.
Несмотря на то, что вам не нужно проходить через все эти проблемы, написание быстрого распределителя может быть проще и в более общем смысле (например, позволяет определять объем памяти, выделяемый / освобождаемый во время выполнения), чем что-то вроде max_align
Вот. max_align
достаточно прост в использовании, но если вам не хватает скорости для выделения памяти (и при условии, что вы уже профилировали свой код и нашли горячие точки в malloc / free / operator new / delete с основными участниками, находящимися в коде, которым вы управляете более), написание собственного распределителя может действительно изменить ситуацию.