如果 C++ 及更高版本保证分配器必须支持过度对齐的类型,这是否意味着我们可以避免创建手动对齐的类型?

If C++17 and above guarantee that allocators must support overaligned types, does that mean we can avoid creating manually-aligned types?

提问人:metamorphosis 提问时间:11/14/2023 最后编辑:HolyBlackCatmetamorphosis 更新时间:11/14/2023 访问量:62

问:

给定一个自定义向量并使用 std::allocator 进行分配,在 C++17 及以上版本下,我们是否仍然需要使用 alignas 创建一个内部过度对齐类型 OT,然后为 OT 分配,并在取消引用迭代器运算符 * 上的指针之前将 OT* reinterpret_cast到 T*,以支持类型的过度对齐?

或者 std::allocator 是否正确对齐,并且取消引用 T* 对于返回对元素的正确过度对齐引用完全有效?

感谢您的任何澄清。

C++ 类型 C++17 分配器 过度对齐

评论

0赞 user17732522 11/14/2023
"我们仍然需要使用 alignas 创建一个内部过度对齐的类型 OT,然后为 OT 分配,并在取消引用迭代器运算符上的指针之前将 OT* reinterpret_cast到 T*,“: 我不完全遵循您的描述,但这听起来像是 UB 开始。
1赞 Ext3h 11/14/2023
该要求表明,分配器必须支持过度对齐。因此,如果你分配 OT,它的工作方式和以前一样,如果你分配 T,你仍然只能保证 T 的对齐。值得一提的是,那里是完全坚果,当时你可以通过聚合将 T 打包到 OT 中,没有任何 UB。添加一个隐式强制转换运算符,你甚至不会注意到它的存在。reinterpret_cast
0赞 Nicol Bolas 11/14/2023
"为了支持类型的过度对齐?目前尚不清楚这在您正在谈论的程序上下文中意味着什么。仅当 不是过度对齐的类型,但您希望分配与 对齐的内存时,该过程才有意义。但如果这是真的,那么就没有“类型的过度对齐”,因为它没有过度对齐。TOTT

答:

6赞 user17732522 11/14/2023 #1

在 C++17 之前,它是否支持过度对齐类型是由实现定义的。std::allocator

在 C++17 的 P0035 中,这一点已更改,现在需要支持所有类型。通常,实现支持哪些对齐方式仍由实现定义,但首先无法定义具有不受支持的对齐方式的类型。

因此,即使 a 在 C++17 中过度对齐,它也会正确地对齐其元素。我不遵循您对实现对齐的“旧”方法的解释,但是在 C++17 之前,如果没有提到的实现定义,就无法使用标准分配器将过度对齐的类型转换为 a。您必须编写自己的 Allocator 来支持过度对齐的类型。你也总是需要,并且仍然需要真正使你的类型过度对齐。std::vector<T>Tstd::vectoralignasT

但是,分配器通常要求不支持所有过度对齐,不幸的是,允许静默忽略对齐。因此,如果使用与 不同的分配器,则必须单独验证它是否支持过度对齐类型的对齐方式。std::allocator