为什么C++标准允许std::max_align_t和__STDCPP_DEFAULT_NEW_ALIGNMENT__不一致?

Why does the C++ standard allow std::max_align_t and __STDCPP_DEFAULT_NEW_ALIGNMENT__ to be inconsistent?

在Visual Studio中,编译64位时:

因此,虽然 std::max_align_t 表示 new 的实现应该 return 指针对齐到 8 字节的倍数,但对齐要求为 16 字节的分配不会调用 void* operator new (std::size_t count, std::align_val_t); 方法,但调用 void* operator new (std::size_t count);(参见 https://en.cppreference.com/w/cpp/memory/new/operator_new)并期望它们 return 一个按 16 字节对齐的指针。

所以分配一个这样定义的结构:

struct alignas(16) S {double m_value;};

将调用标准运算符 new(没有 std::align_val_t 参数)并期望它按 16 个字节对齐,而 std::max_align_t 仅指定它应按 8 个字节对齐.

这意味着当否决 new 运算符时,您必须将所有内容对齐至少 16 个字节,即使 8 个字节就足够了。

C++17 中有两层 over-aligned 类型:扩展和 new-extended。 std::max_align_t定义了不扩展的最大对齐,__STDCPP_DEFAULT_NEW_ALIGNMENT__定义了不扩展的最大对齐。new-extended.

New-extended对齐,顾名思义,就是你用new.

分配的东西的对齐方式

基本上,常规 operator new 将 return 适合任何对象的内存,最大为 new-extended 对齐大小。任何更大的对齐方式都倾向于使用 operator new 重载来指定正在创建的类型的对齐方式。当然,一般情况下,就像 over-aligned 类型一样有条件地支持。 operator delete 销毁与此类类型关联的内存的调用也是如此。

Visual Studio说的是over-aligned不考虑的最大对齐是8字节,但是operator new分配的内存的对齐是16字节。


This means that when overruling the new operators, you are forced to align everything on at least 16 bytes, even if 8 bytes would be sufficient.

基本上,是的。无法请求实现告诉您原始 operator new/delete 重载请求的对齐方式。

现在,您可以在 object-by-object 的基础上重载该对象的 operator new 以直接调用 alignment-specific operator new。但是你不能让编译器这样做。