关于在C ++ 17中使用alignas及其与Visual Studio / MVC ++的_declspec(align(...))的关系

时间:2017-11-17 10:03:11

标签: c++ visual-studio visual-studio-2017 c++17

为了确保C ++中某些数据结构的用户指定内存对齐,我认为需要注意三个用例并进行适当处理(如果我错过了一些用例,请随意添加它们):

  1. 静态内存分配;
  2. 动态内存分配;
  3. 容器中的内存分配(例如std::vector)和智能指针(例如std::shared_ptr)。
  4. C ++ 11通过添加允许手动指定对齐的alignas说明符来处理静态内存分配。 C ++ 17通过隐式覆盖operator newoperator new[]operator deleteoperator 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::vectorstd::shared_ptr等内部处理(使用alignof)?

    Visual Studio(与MVC ++编译器密切相关)支持自Visual Studio 2015以来的alignasalignof关键字。由于仍为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

0 个答案:

没有答案