对齐成员变量和动态分配

时间:2014-02-17 07:07:49

标签: c++ c++11 sse

所以基本上,这是我到目前为止所得到的。我有一个mat4类,它由__m128组成,需要在16字节边界上对齐:

_MM_ALIGN16
class mat4
{
   ...
};

我有另一个本身未对齐的类,但包含mat4

class OtherClass
{
private:
   mat4 matrix;
   // Other data whose alignment doesn't really matter
   ...
};

我需要动态分配OtherClass,ala:

的实例
OtherClass* stuff = new OtherClass[n];

如何保证实例中的mat4正确对齐,同时仍然调用mat4的构造函数?

我可以(通常更喜欢)使用C ++ 11的功能,也许aligned_storage是我正在寻找的?在这种情况下我如何使用它?

3 个答案:

答案 0 :(得分:1)

您可以使用 placement new 将内存分配与对象创建分离:

/* Memory allocation */
#ifdef _MSC_VER
     void *buffer = _aligned_malloc(n * sizeof(OtherClass), 16);
#else
     void *buffer = memalign(16, n * sizeof(OtherClass));
#endif
/* Object construction */
OtherClass *array = new (buffer) OtherClass[n];

/* Use your objects */
...

/* Object destruction */
for (size_t i = 0; i < n; i++) {
    array[i].~OtherClass();
}
/* Memory deallocation */
#ifdef _MSC_VER
     _aligned_free(buffer);
     buffer = nullptr;
#else
     free(buffer);
     buffer = nullptr;
#endif

更多C ++方法是将std :: vector与对齐的分配器一起使用。

答案 1 :(得分:1)

您可以使用std::aligned_storage来定义具有指定路线的未初始化存储空间以及展示位置新运营商。

例如:

class OtherClass
{
private:
    using storage_t = typename std::aligned_storage<sizeof(mat4), 16>::type;

    storage_t _storage;

    mat4* address()  {
        return static_cast<mat4*>(static_cast<void*>(&_storage));
    }

    mat4 const* address() const {
        return static_cast<mat4 const*>(static_cast<void const*>(&_storage));
    }

public:

    OtherClass() { 
        new(address()) mat4();
    }
    OtherClass(OtherClass const& rhs) {
        new(address()) mat4(*rhs.address());
    }
    OtherClass& operator=(OtherClass const& rhs) {
        *address() = *rhs.address();
    }

    ~OtherClass() { 
       address()->~mat4(); 
    }  

    // setter
    template<typename... Args,
        class Enable = typename std::enable_if<
            std::is_constructible<mat4, Args...>::value
        >::type
    >
    void setMat(Args&&... args) {
        new(address()) mat4(std::forward<Args>(args) ...);
    }

    // getter
    mat4 const& getMat() const {
        return *address();
    }

    mat4& getMat() {
        return *address();
    }
    ...
};

另见:  std::aligned_storage

关于SO的类似问题:C++ Allocate Storage for Object without Initializing it?

答案 2 :(得分:0)

union alignas (16) { __m128 _v; float _s[4]; }; - 作为一个例子,关于严格别名的常见警告 - 不能保证堆存储对齐。

您可以通过查询std::max_align_t类型来避免新的/删除实施,如this答案中所述。

否则,您可能需要重新实施全局运算符new / delete函数。我不认为每类方法就足够了。例如,考虑具有Camera成员的班级mat4;如果在堆栈上实例Camera,则应保留mat4成员对齐。如果在堆上创建了Camera对象,我看不出如何强制执行此操作。