为了确保C ++中某些数据结构的用户指定内存对齐,我认为需要注意三个用例并进行适当处理(如果我错过了一些用例,请随意添加它们):
std::vector
)和智能指针(例如std::shared_ptr
)。 C ++ 11通过添加允许手动指定对齐的alignas
说明符来处理静态内存分配。 C ++ 17通过隐式覆盖operator new
,operator new[]
,operator delete
和operator delete[]
来处理动态内存分配。虽然,我注意到C ++ 17还增加了这些运算符的重载以及额外的对齐参数?
像std::vector
这样的容器可以分配一大块原始内存来存储容器元素。然后可以通过将指针传递到此块中的某个位置operator new
(placement new)来分配容器元素。 std::shared_ptr
有一种类似的情况,它使用在调用std::make_shared
的情况下分配在一起的控制和数据块(对于只使用数据块的std::unique_ptr
不同,在调用operator new
后将与std::make_unique
分配。为了确保容器元素和std::shared_ptr
数据块的正确内存对齐,std
提供了传递将用于这些分配的allocator的可能性。鉴于为某些数据结构指定了alignas
,是否仍然需要通过这样的分配器来确保在C ++ 17中正确的内存对齐?或者由std::vector
,std::shared_ptr
等内部处理(使用alignof
)?
Visual Studio(与MVC ++编译器密切相关)支持自Visual Studio 2015以来的alignas
和alignof
关键字。由于仍为Visual Studio 2013维护了一些Microsoft库,因此使用{ {1}}无处不在。 _declspec(align(...))
只负责静态内存分配。要处理动态内存分配,通常会公开继承以下无状态结构:
_declspec(align(...))
所以我想知道template< typename TDerived >
struct AlignedNew {
static void* operator new (size_t size) {
const size_t alignment = __alignof(TDerived);
static_assert(alignment > 8);
void* ptr = _aligned_malloc(size, alignment);
if (!ptr)
throw std::bad_alloc();
return ptr;
}
static void operator delete (void* ptr) {
_aligned_free(ptr);
}
static void* operator new[] (size_t size) {
return operator new(size);
}
static void operator delete[] (void* ptr) {
operator delete(ptr);
}
};
+继承此结构和_declspec(align(...))
的组合是否提供了相同的功能,或alignas(...)
是否提供了相同但功能更强的alignas(...)
+继承这个结构?如果是这种情况,我可以安全地将_declspec(align(...))
替换为_declspec(align(...))
并删除alignas(...)
结构吗?
关于前C ++ 17时代的最后一部分他们是similar question,但是接受的唯一答案的第一个点并不是非常深刻,imho。
请注意,此问题中提到了多个C ++标准,以及多个MVC ++版本,这些版本仅是各种C ++标准的部分实现。我主要关心的是C ++ 17(以及latest iteration of Visual Studio 2017)