2

如果一个类T有对齐要求,例如由alignas关键字指定的,是否std::optional<T>保证boost::optional<T>遵守所述对齐?

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

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

4

2 回答 2

6

根据 C++17 标准草案,一个符合标准的 std::optional 实现必须尊重其对齐要求:value_type

23.6.3 类模板可选 [optional.optional]

(...) 包含的值应分配在与类型 T 适当对齐的可选存储区域中。

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

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

于 2017-09-04T14:06:28.777 回答
2

在 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是一个线索;文档没有提到第二个模板参数是可选的,默认为 -1,这意味着,boost::detail::max_align这意味着使用包含一堆长度为 128 位的原始类型的联合类型的对齐方式。所以(粗略阅读)Boost 似乎比 GNU 更悲观一些,但也会让你的对齐方式正确。

于 2017-09-04T14:01:57.770 回答