在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中定义了与这些数量相对应的两个术语:
扩展的比对由大于
alignof(std::max_align_t)
的比对表示。 [...]具有扩展对齐要求的类型是过度对齐类型。 [...] 新扩展的比对由大于__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
,可能是未定义的行为吗?
答案 0 :(得分:2)
std::max_align_t
:最大标量类型的对齐方式__STDCPP_DEFAULT_NEW_ALIGNMENT__
:已分配内存的对齐方式如果我没看错标准,则新扩展的比对是指void* operator new( std::size_t count, std::align_val_t al);
的所有变体(带有std::align_val_t
的变体)。
因此,假设__STDCPP_DEFAULT_NEW_ALIGNMENT__
为8,std::max_align_t
为16,则long double的分配将必须调用::operator new(16, std::align_val_t(16));
。编译器在不引起您注意的情况下将为您做些事情。
实际上,我相信有一些Linux实现可以保证新的对齐方式为8。(moz)jemalloc是其中之一,为此,github-issue似乎确认最小对齐方式为8而不是16(我没有找到有关它的官方文档)
如果要使用这种实现,则必须更新__STDCPP_DEFAULT_NEW_ALIGNMENT__
常量,有关更多详细信息,请参阅我的问题之一:Overloading operator new with smaller default alignment。
要回答您的最后一个问题,我读了auto x = ::new(::operator new(sizeof(T))) T;
,明确地将运算符称为new,而不是简单地进行new T
,在这种情况下,如果T要求的对齐方式大于默认的新对齐方式。请注意,如果两个常量相等,这也适用,因为您可以在类中添加alignas
来更改对齐方式。
使用这些类需要格外小心,因为在与std::vector
一起使用时使用自定义分配器。