所以基本上,这是我到目前为止所得到的。我有一个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
是我正在寻找的?在这种情况下我如何使用它?
答案 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();
}
...
};
关于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
对象,我看不出如何强制执行此操作。