std::可选和提升::可选是否尊重托管对象的对齐限制?
Do std::optional and boost::optional respect alignment restrictions of the managed object?
如果类T
具有对齐要求,例如由alignas
关键字指定的要求,std::optional<T>
和boost::optional<T>
保证遵守所述对齐吗?
如果它们只是T
对象和bool initialized
的包装类,那么它们将根据需要自动对齐其T
成员,但标准和提升文档指出它们可以容纳任何对象并且可以很好地处理昂贵的构造对象。由此我了解到它们不仅仅是包含T
.相反,它们似乎分配了一个缓冲区,在该缓冲区上手动构建或销毁T
。因此,C++语言不会自动对齐缓冲区,因为它不是T
类型。
那么,std::optional<T>
和boost::optional<T>
是否正确对齐其托管T
对象?他们是否还提供符合对齐要求的optional<T>::operator new
和optional<T>::operator new[]
?
根据 C++17 标准草案,符合 std::optional 的实现必须尊重其value_type
的对齐要求:
23.6.3 类模板可选 [可选.可选]
(... 所包含的值应分配给与T型适当对齐的可选存储区域。
实现者可以使用可能包含值作为成员的联合,以确保正确对齐。
正如托马斯在我查找它时已经提到的那样,boost::optional 确实通过使用aligned_storage<T>
确保正确对齐
在 GNU C++ 实现中,std::optional
派生自_Optional_Base<_Tp>
,而 又包含一个_Optional_payload<_Tp>
。这是一个具有多个专用化的模板,所有这些专用化都包含以下成员:
using _Stored_type = remove_const_t<_Tp>;
struct _Empty_byte { };
union {
_Empty_byte _M_empty;
_Stored_type _M_payload;
};
bool _M_engaged = false;
如您所见,_M_payload
实际上是强类型的,因此在此实现中应正确继承任何对齐属性。
提升实现不使用联合。相反,boost::optional<T>
派生自optional_base<T>
,它只包含:
typedef aligned_storage<T> storage_type ;
bool m_initialized ;
storage_type m_storage ;
aligned_storage
的名称是一个线索;文档没有提到第二个模板参数是可选的,默认为 -1,这意味着boost::detail::max_align
,这意味着使用对齐方式包含一堆长度不超过 128 位的基元类型的联合类型。所以(粗略阅读)Boost似乎比GNU更悲观一些,但也会让你的对齐正确。
- 哪些值存储在对齐的结构/类对象的填充字节中
- 如何分配适合容纳 T 类型对象的缓冲区(可能过度对齐、可能有运算符 new 等)
- 对象地址是否保证是其类型对齐的倍数
- MIPS 和 x86_64 之间的对象对齐差异
- Sizeof 舍入到对齐方式,但编译器仍将对象放在剩余的字节中
- 自动热键:重新映射 MS Visio 的快捷方式,以将手动选择的对象对齐到顶部(好像按:"AlignTop")
- 在以下情况下,是否可以分配未对齐的对象?
- 如何分配内存对齐C++对象数组?
- STD :: Aligned_Storage如何正确对齐任何对象的存储
- std::可选和提升::可选是否尊重托管对象的对齐限制?
- 如何强制对齐堆分配的对象
- 将对象位置与网格对齐
- 对象数组对齐与 __attribute__aligned() 或 alignas()
- 对象数组作为链表中的字符数组 - 我对对齐的假设是否有效
- 如何使用指针合法地访问对齐错误的对象
- 我不明白在下面的代码中将 char buffer[] 与 X 类型的对象对齐的原因
- 标准是否要求自动存储中的对象对任何类型都具有正确的对齐方式(例如malloc)
- xcode中的对象字节对齐
- 子对象的对齐小于基对象的对齐
- 类与虚拟函数的成员对象对齐和动态分配的问题