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

时间:2019-05-16 14:59:44

标签: c++ visual-studio c++-standard-library

在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个字节。

  • 我想念什么吗?
  • 这是Visual Studio实现C ++ / STL的错误吗?
  • 这是C ++ / STL标准中的错误吗?

1 个答案:

答案 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。但是您不能使编译器这样做。