std::optional 和 boost::optional 是否遵守托管对象的对齐限制?

Do std::optional and boost::optional respect alignment restrictions of the managed object?

如果 class T 有对齐要求,例如由 alignas 关键字指定的要求,则 std::optional<T>boost::optional<T> 保证遵守说对齐?

如果它们只是 class 对象 T 对象和 bool initialized 的包装器,那么它们会根据需要自动对齐它们的 T 成员,但是标准并提升文档状态,它们不能容纳任何对象并且可以很好地处理构建对象的昂贵问题。由此我了解到它们不只是包含 T。相反,他们似乎分配了一个缓冲区,在该缓冲区上手动构造或销毁 T 。因此,C++语言不会自动对齐缓冲区,因为它不是T.

类型

那么,std::optional<T>boost::optional<T> 是否正确对齐了它们的托管 T 对象?他们是否还提供符合对齐要求的 optional<T>::operator newoptional<T>::operator new[]

在 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 实现不使用联合。相反,boost::optional<T> 派生自 optional_base<T>,它仅包含:

 typedef aligned_storage<T> storage_type ;
 bool m_initialized ;
 storage_type m_storage ;

aligned_storage的名字是一条线索; docs 不要提到第二个模板参数是可选的,默认为 -1,这意味着 boost::detail::max_align,这意味着使用对齐一个包含一堆原始类型的联合类型,最多 128 位在长度上。所以(从粗略的阅读来看)Boost 似乎比 GNU 更悲观一点,但也会让你的对齐方式正确。

std::optional 的一致性实现必须 根据 C++17 标准草案遵守其 value_type 的对齐要求:

23.6.3 Class template optional [optional.optional]

(...) The contained value shall be allocated in a region of the optional storage suitably aligned for the type T.

实施者可以使用可能包含值作为成员的联合,确保正确对齐。

正如 Thomas 在我查找时提到的那样,boost::optional 确实通过使用 aligned_storage<T>

确保正确对齐