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

标签 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 字节对齐。

这意味着当否决 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/

相关文章:

c++ - 标准实验锁存器和屏障使用 ptrdiff_t

c++ - 修改后的 std::invoke/std::apply,将可调用对象作为 void* - 可能吗?

c++ - 标准库中的非推导上下文,如 'boost::mpl::identity<T>::type'?

c++ - clang-tidy 忽略 Windows 上的可读性标识符命名

c++ - 具有不同通知的观察者模式

c++ - 我如何在 qtslot 中调用我的函数?

visual-studio - Visual Studio : How to make its UI fast, 精益化和最小化?

visual-studio - Visual Studio "Search Solution Explorer"已禁用

c++ - 票据打印作业

c++ - 如何在 Visual Studio 2012 上使用带控制台的 GUI Windows 应用程序?