为什么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位时:
sizeof(std::max_align_t)
是 8
__STDCPP_DEFAULT_NEW_ALIGNMENT__
是 16
因此,虽然 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 个字节就足够了。
- 我是不是漏掉了什么?
- 这是 Visual Studio 实现 C++/STL 的方式的错误吗?
- 或者这是 C++/STL 标准中的错误?
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
。但是你不能让编译器这样做。
在Visual Studio中,编译64位时:
sizeof(std::max_align_t)
是 8__STDCPP_DEFAULT_NEW_ALIGNMENT__
是 16
因此,虽然 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 个字节就足够了。
- 我是不是漏掉了什么?
- 这是 Visual Studio 实现 C++/STL 的方式的错误吗?
- 或者这是 C++/STL 标准中的错误?
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
。但是你不能让编译器这样做。