Работает ли спецификатор alignas с ‘new’?

Мой вопрос довольно прост;

Работает ли спецификатор alignas с ‘new’? То есть, если структура определена для выравнивания, будет ли она выравниваться при выделении с новым?

9

Решение

Если выравнивание вашего типа не выровнено, то да, по умолчанию new буду работать. «Выровненный» означает, что выравнивание, указанное вами в alignas больше, чем alignof(std::max_align_t), По умолчанию new будет работать с не выровненными типами более или менее случайно; Распределитель памяти по умолчанию всегда будет выделять память с выравниванием, равным alignof(std::max_align_t),

Если выравнивание вашего типа слишком выровнено, вам не повезло. Ни по умолчанию newни какой глобальный new Оператор, которого вы напишете, сможет даже узнать требуемое выравнивание типа, не говоря уже о выделении памяти, соответствующей ему. Единственный способ помочь в этом случае — перегрузить класс operator new, который сможет запросить выравнивание класса с alignof,

Конечно, это не будет полезно, если этот класс используется как член другого класса. Нет, если этот другой класс также не перегружен operator new, Так просто new pair<over_aligned, int>() не сработает

Предложение для C ++ 17 (которое было принято) добавляет поддержка динамического выделения выровненных типов, имея перегрузки operator new/delete что взять alignof типа выделяется. Это также будет поддерживать выравнивания меньше максимального выровненного типа, поэтому ваш распределитель памяти не всегда должен возвращать память, выровненную по alignof(std::max_align_t),

Это, как говорится, компиляторы не требуется поддерживать перегруженные типы на всех.

12

Другие решения

Нет. Структура будет дополнена запрошенным выравниванием, но она не будет выровнена. Однако есть вероятность, что это будет разрешено в C ++ 17 (Тот факт, что это предложение C ++ 17 существует, должно быть довольно хорошим доказательством того, что это не может работать в C ++ 11).

Я видел, как это работает с некоторыми распределителями памяти, но это была чистая удача. Например, некоторые распределители памяти будут выравнивать свои выделения памяти в степени 2 запрошенного размера (до 4 КБ) в качестве оптимизации для распределителя (уменьшить фрагментацию памяти, возможно, упростить повторное использование ранее освобожденной памяти и т. Д.) , Однако новые реализации / malloc, которые включены в системы OS X 10.7 и CentOS 6, которые я тестировал, не делают этого и терпят неудачу со следующим кодом:

#include <stdlib.h>
#include <assert.h>

struct alignas(8)   test_struct_8   { char data; };
struct alignas(16)  test_struct_16  { char data; };
struct alignas(32)  test_struct_32  { char data; };
struct alignas(64)  test_struct_64  { char data; };
struct alignas(128) test_struct_128 { char data; };
struct alignas(256) test_struct_256 { char data; };
struct alignas(512) test_struct_512 { char data; };

int main() {
test_struct_8   *heap_8   = new test_struct_8;
test_struct_16  *heap_16  = new test_struct_16;
test_struct_32  *heap_32  = new test_struct_32;
test_struct_64  *heap_64  = new test_struct_64;
test_struct_128 *heap_128 = new test_struct_128;
test_struct_256 *heap_256 = new test_struct_256;
test_struct_512 *heap_512 = new test_struct_512;

#define IS_ALIGNED(addr,size)   ((((size_t)(addr)) % (size)) == 0)

assert(IS_ALIGNED(heap_8, 8));
assert(IS_ALIGNED(heap_16, 16));
assert(IS_ALIGNED(heap_32, 32));
assert(IS_ALIGNED(heap_64, 64));
assert(IS_ALIGNED(heap_128, 128));
assert(IS_ALIGNED(heap_256, 256));
assert(IS_ALIGNED(heap_512, 512));

delete heap_8;
delete heap_16;
delete heap_32;
delete heap_64;
delete heap_128;
delete heap_256;
delete heap_512;

return 0;
}
8

По вопросам рекламы [email protected]