__STDCPP_DEFAULT_NEW_ALIGNMENT__ 和 alignof(std::max_align_t) 之间的顺序

Order between __STDCPP_DEFAULT_NEW_ALIGNMENT__ and alignof(std::max_align_t)

在 x86-64/Linux 上使用 GCC 和 Clang alignof(std::max_align_t)__STDCPP_DEFAULT_NEW_ALIGNMENT__ 都等于 16

在 x86-64/Windows 上使用 MSVC alignof(std::max_align_t)8 并且 __STDCPP_DEFAULT_NEW_ALIGNMENT__16

标准定义了[basic.align]/3中这些量对应的两个术语:

An extended alignment is represented by an alignment greater than alignof(std​::​max_­align_­t). [...] A type having an extended alignment requirement is an over-aligned type. [...] A new-extended alignment is represented by an alignment greater than _­_­STDCPP_­DEFAULT_­NEW_­ALIGNMENT_­_­.

我看不出这意味着两个值之间的任何排序,除非我将术语“new-extended”解释为暗示“extended " 从拼写。

是否允许符合 C++ 标准的实现

alignof(std::max_align_t) > __STDCPP_DEFAULT_NEW_ALIGNMENT__

?

如果是,这是否意味着对象创建通过

auto x = ::new(::operator new(sizeof(T))) T;

可能是某些非过度对齐类型的未定义行为 T?

如果我读的标准是正确的,新的扩展对齐是指 void* operator new( std::size_t count, std::align_val_t al); 的所有变体(那些带有 std::align_val_t 的变体)。

所以假设8的__STDCPP_DEFAULT_NEW_ALIGNMENT__和16的std::max_align_t,分配long double就得调用::operator new(16, std::align_val_t(16));。您的编译器必须在您不注意的情况下为您做一些事情。

实际上,我相信有 linux 实现可以保证新的对齐方式为 8。(moz)jemalloc is one of them, for which this github-issue 似乎确认最小对齐方式是 8 而不是 16。(我没有'找到关于它的官方文档)

如果你想使用这样的实现,你必须更新 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 常量,有关更多详细信息,请参阅我的问题之一:.

为了回答你的最后一个问题,我读到 auto x = ::new(::operator new(sizeof(T))) T; 是明确调用 operator new 而不是简单地做 new T,在这种情况下,如果 T 需要对齐,我会假设你确实有 UB大于默认的新对齐方式。请注意,如果两个常量相等,这也成立,因为您可以将 alignas 添加到 class 以更改对齐方式。

使用这些 classes 需要格外小心,因为在与 std::vector 一起使用时使用自定义分配器。