在 Visual Studio 中,编译 64 位时:
sizeof(std::max_align_t)
为 8__STDCPP_DEFAULT_NEW_ALIGNMENT__
为 16
因此,尽管 std::max_align_t
表明 new
的实现应该返回与 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 ) 并期望它们返回一个按 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 中有两层过度对齐类型:extended 和 new-extended。 std::max_align_t
定义了未扩展的最大对齐,__STDCPP_DEFAULT_NEW_ALIGNMENT__
定义了未新扩展的最大对齐。
New-extended alignment,顾名思义,就是你用new
分配的东西的对齐方式。
基本上,常规的 operator new
将返回适合任何对象的内存,直到新扩展的对齐大小。任何更大的对齐方式都倾向于使用 operator new
重载来指定正在创建的类型的对齐方式。当然,像一般的过度对齐类型一样有条件地支持。 operator delete
调用也是如此,以销毁与此类类型关联的内存。
Visual Studio 所说的是不被视为过度对齐的最大对齐是 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
重载请求的对齐方式。
现在,您可以逐个对象地重载该对象的 operator new
以直接调用对齐特定的 operator new
。但是你不能让编译器这样做。
关于c++ - 为什么 C++ 标准允许 std::max_align_t 和 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 不一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56171482/