【发布时间】:2012-11-08 03:04:03
【问题描述】:
我目前正在使用aligned_storage 来实现类似于boost::optional 的“可选”类型。为了做到这一点,我有一个像这样的班级成员:
typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type t_;
我使用placement new 来创建对象,但是我没有将返回的指针存储在任何地方。相反,我在我的所有成员函数中访问对象的基础类型,就像这样(显然通过检查以确保对象有效,通过也存储在我的 Optional 类型中的布尔标志):
T const* operator->() const {
return static_cast<T const*>(static_cast<void const*>(&t_));
}
我的问题是这是否安全。我的理解是,我对放置 new 的使用改变了对象的“动态类型”,只要我继续使用该类型访问内存就可以了。但是,我不清楚我是否必须保留从新位置返回的指针,或者是否允许我在需要访问它时只转换为基础类型。我已经阅读了 C++11 标准的第 3.10 节,但是我的标准语不够流利,无法确定。
如果可能的话,如果你能在你的回答中参考标准,我会感觉更好(它有助于我晚上睡觉:P)。
【问题讨论】:
-
我认为这归结为 operator new 返回的指针是否可能与结果对象的地址不同。 C++03 标准的第 5.3.4.14 节指出,如果对象是数组,则不一定相同,这使我相信否则它会相同。
-
最终,它的实现定义了分配的基地址是否是对象占用空间的第一个字节。因此,取
new的结果更正确。明显的情况是通过new[]分配;实现通常将销毁数组对象所需的信息存储在分配的前导字节中。 -
注意 C++17 中有
std::optional...
标签: c++ undefined-behavior language-lawyer strict-aliasing type-punning