Как уже упоминал Питер Кордес в комментариях выше, проблема в том, что new
не учитывает расширенное выравнивание до C ++ 17.(См. [P0035R4] , который был принят в C ++ 17, чтобы сделать new
пригодным для использования в памяти с более чем alignof(maxalign_t)
выравниванием).
GCC7 и более поздние поддерживает выровненный новый с -std=gnu++17
или -std=c++17
(или просто -faligned-new
).Ваш код будет Just Work ™ и автоматически передаст необходимое выравнивание на operator new
, если вы включите эти опции .
Но более старый GCC, включая ваш 6.3, делает не , поэтому вам придется вручную убедиться, что память выровнена правильно.Есть несколько способов сделать это.
_mm_alloc
уже упоминалось в комментариях.В GCC _mm_alloc
, по-видимому, в основном соответствует posix_memalign
, так что вы также можете просто использовать это напрямую.Переносимое решение C ++ 11 будет выделять достаточно большой буфер для размещения объекта вашего класса плюс любое пространство, необходимое для заполнения в начале, чтобы обеспечить правильное выравнивание.Затем вы можете использовать std::align
и для размещения нового , чтобы построить свой объект по подходящему адресу.
Все это, независимо от того, какой метод распределенияПравильно выровненную память, которую вы выберете, я бы настоятельно рекомендовал инкапсулировать в этом, предоставляя функции выделения и освобождения для вашего класса.Требование выравнивания является свойством самого типа, и пользователь вашего класса не должен знать, что из-за деталей реализации, таких как тот факт, что он имеет член типа __m256i
, любой объект типа MyClass
имеет расширенные требования выравнивания, которые должны учитываться всякий раз, когда такой объект выделяется с помощью нового выражения.Вам следует либо запретить создание объектов этого типа с помощью нового выражения, либо предоставить необходимые средства для правильной работы типа с новыми выражениями ...
Решение C ++ 11 может выглядеть следующим образом:
#include <cstddef>
#include <memory>
#include <immintrin.h>
class MyClass
{
__m256i value;
public:
MyClass(const int* arr)
{
this->value = _mm256_set_epi32(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7]);
}
void* operator new(std::size_t size)
{
return _mm_malloc(size, alignof(MyClass));
}
void* operator new[](std::size_t size)
{
return _mm_malloc(size, alignof(MyClass));
}
void operator delete(void* ptr)
{
_mm_free(ptr);
}
void operator delete[](void* ptr)
{
_mm_free(ptr);
}
};
int main()
{
int arr[8] = {0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7};
auto m = std::unique_ptr<MyClass> { new MyClass(arr) };
}
живой пример здесь