在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个字节。 / p>
这意味着在推翻new
运算符时,即使8个字节就足够了,您也必须将所有内容至少对齐16个字节。
答案 0 :(得分:1)
C ++ 17中有两层过度对齐的类型:扩展和新扩展。 std::max_align_t
定义未扩展的最大对齐方式,__STDCPP_DEFAULT_NEW_ALIGNMENT__
定义未新扩展的最大对齐方式。
顾名思义,新扩展的对齐方式是关于您分配给new
的事物的对齐方式。
基本上,常规operator new
将返回适合任何对象的内存,直到新扩展的对齐大小。任何更大的对齐方式都倾向于使用operator new
重载来指定要创建的类型的对齐方式。当然,有条件地支持,就像一般情况下过度对齐的类型一样。 operator delete
调用销毁与此类类型关联的内存也是如此。
Visual Studio所说的是,最大对齐方式(不认为过度对齐)是8字节,但是operator new
分配的内存对齐方式是16字节。
这意味着在推翻
new
运算符时,即使8个字节就足够了,您也必须将所有内容至少对齐16个字节。
从本质上讲,是的。没有办法要求实现告诉您原始的operator new/delete
重载要求什么对齐。
现在,您可以在逐个对象的基础上重载该对象的operator new
来直接调用特定于对齐方式的operator new
。但是您不能使编译器这样做。