在 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 和 alignof(std::max_align_
Order between __STDCPP_DEFAULT_NEW_ALIGNMENT__ and alignof(std::max_align_t)
在x86-64/Linux上,GCC和Clangalignof(std::max_align_t)
和__STDCPP_DEFAULT_NEW_ALIGNMENT__
都等于16
。
在x86-64/Windows上使用MSVC,alignof(std::max_align_t)
8
__STDCPP_DEFAULT_NEW_ALIGNMENT__
16
。
该标准定义了 [basic.align]/3 中对应于这些数量的两个术语:
扩展对齐方式由大于
alignof(std::max_align_t)
的对齐方式表示。[...]具有扩展对齐要求的类型是过度对齐类型。[...]新扩展的对齐方式由大于__STDCPP_DEFAULT_NEW_ALIGNMENT__
的对齐方式表示。
我不认为这意味着两个值之间的任何排序,除非我将术语">新扩展"解释为拼写中的">扩展"。
是否允许具有C++标准的符合实现
alignof(std::max_align_t) > __STDCPP_DEFAULT_NEW_ALIGNMENT__
?
如果是这样,这是否意味着通过
auto x = ::new(::operator new(sizeof(T))) T;
可能是某些未过度对齐的类型T
的未定义行为?
std::max_align_t
:最大标量类型的对齐方式__STDCPP_DEFAULT_NEW_ALIGNMENT__
:分配内存的对齐方式
如果我正确阅读标准,则新扩展的对齐方式是指void* operator new( std::size_t count, std::align_val_t al);
的所有变体(带有std::align_val_t
的变体(。
所以假设__STDCPP_DEFAULT_NEW_ALIGNMENT__
8,std::max_align_t
16,长双的分配就得叫::operator new(16, std::align_val_t(16));
。您的编译器必须在您不注意的情况下为您执行一些操作。
在实践中,我相信有一些 linux 实现可以保证新的 8 对齐。(Moz(Jemalloc 就是其中之一,这个 github 问题似乎证实了最小对齐方式是 8 而不是 16。(我没有找到有关它的官方文档(
如果要使用此类实现,则必须更新__STDCPP_DEFAULT_NEW_ALIGNMENT__
常量,有关更多详细信息,请参阅我的一个问题:重载运算符新,默认对齐方式较小。
为了回答您的最后一个问题,我auto x = ::new(::operator new(sizeof(T))) T;
读为明确调用运算符 new 而不是简单地执行new T
,在这种情况下,如果 T 需要大于默认新对齐方式的对齐方式,我会假设您确实有 UB。请注意,如果两个常量相等,这也成立,因为您可以向类中添加alignas
以更改对齐方式。
使用这些类型的类需要格外小心,例如在与std::vector
一起使用时使用自定义分配器。
- 关于 std::min, std::max 中的比较运算符的混淆
- std::max() 函数与定点实现的比较中的问题
- 使用 CImg 库的 std::min 和 std::max 的编译问题
- 在枚举类型上使用std::max是不是一种糟糕的做法
- 如何在 C++11 中将 std::max 与自定义比较器一起使用?
- C++是否在 std::min 和 std::max 下标准化 std::optional 的行为?
- 编译器无法推断 std::max 的重载
- 为什么 c++ 编译器在对两种不同类型的数值变量使用"std::max()"函数时会出现错误
- 执行 std::min(0.0, 1.0) 和 std::max(0.0, 1.0) 会产生未定义的行为
- 自动变量可存储函数指针到std :: max
- std :: max带有动态数组
- std :: max,但用于模板参数
- 如果std::max()通过引用返回(这是必须的),这是否会导致悬空引用
- std::max with lambda and auto
- 在c++11中,如何在向量上调用std::max
- 有没有办法防止开发人员使用std::min, std::max
- 关于std::min()和std::max()的c++可变模板版本的思考
- std::max-需要一个标识符
- 将std::max转换为Java
- 如何在不重载比较操作符的情况下为std::max专门化自定义类型