aligned_storage和严格的混叠
aligned_storage and strict aliasing
我目前正在使用 aligned_storage 来实现类似于 boost::Optional 的"可选"类型。为了完成这一点,我有一个这样的类成员:
typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type t_;
我使用放置 new 来创建对象,但是我不将返回的指针存储在任何地方。相反,我在我的所有成员函数中访问对象的基础类型,如下所示(显然通过同样存储在我的 Optional 类型的布尔标志进行检查以确保对象有效):
T const* operator->() const {
return static_cast<T const*>(static_cast<void const*>(&t_));
}
我的问题是这是否安全。我的理解是,我对放置 new 的使用会改变对象的"动态类型",只要我继续使用该类型访问内存,我就可以了。但是,我不清楚我是否必须持有从放置 new 返回的指针,或者是否允许我在需要访问它时只转换为基础类型。我已经阅读了 C++11 标准的第 3.10 节,但是我的标准语言不够流利,无法确定。
如果可能的话,如果你能在你的答案中参考标准,我会感觉更好(它可以帮助我晚上睡觉:P)。
ABICT您的使用是安全的。
- 放置 T 类型的对象的新位置将创建一个从传入的地址开始的对象。
§5.3.4/10 说:
新表达式将请求的空间量传递给 分配函数作为 std::size_t 类型的第一个参数。那 参数应不小于正在创建的对象的大小; 它可能大于正在创建的对象的大小,仅当 对象是一个数组。
对于非数组对象,分配的大小不能大于对象的大小,因此对象表示必须从分配的内存的开头开始才能适应。
放置 new 返回传入的指针(参见 § 18.6.1.3/2)作为"分配"的结果,因此构造对象的对象表示将从该地址开始。
T*
类型和void*
之间的static_cast<>
和隐式转换,如果对象是完整的对象,则在指向对象的指针和指向其存储的指针之间进行转换。
§4.10/2 说:
类型为"指向 cv T 的指针"的 prvalue,其中 T 是对象类型,可以是 转换为类型为"指向 CV 无效的指针"的 PR值。结果 将"指向 cv T 的指针"转换为"指向 cv void 的指针"指向 类型 T 的对象所在的存储位置的开始,如 如果对象是 T 类型的最派生对象 (1.8) [...]
这将定义要转换的隐式转换,如前所述。此外 §5.2.9[expr.static.cast]/4 定义了显式转换的static_cast<>
,其中隐式转换的存在与隐式转换具有相同的效果:
否则,可以将表达式
e
显式转换为类型T
使用表单static_cast
static_cast<T>(e)
如果声明T t(e);
的格式很好,对于一些发明的临时变量t
(8.5)。 这种显式转换的效果与执行 声明和初始化,然后使用临时 变量作为转换的结果。[...]
对于逆static_cast<>
(从void*
到T*
),§5.2.9/13 指出:
类型为"指向 cv1 void 的指针"的 prvalue 可以转换为 prvalue 类型为"指向 cv2 T 的指针",其中 T 是对象类型,cv2 是 简历资格与简历1相同,或比CV1更高。[...] 指向对象的指针类型的值转换为"指向 cv void 的指针" 和回来,可能具有不同的简历资格,应有其 原始值。
因此,如果有一个指向T
对象的存储的void*
(这是将T*
隐式转换为对象的指针值),则将其static_cast
到T*
将生成指向该对象的有效指针。
回到你的问题,前面几点暗示如果你有
typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type t_;
void * pvt_ = &t_;
T* pT = new (&t_) T(args...);
void * pvT = pT;
然后
*pT
的存储正好覆盖了t_
存储的第一个大小(T)字节,因此pvT == pvt_
pvt_ == static_cast<void*>(&t_)
static_cast<T*>(pvT) == pT
- 综合起来,产生
static_cast<T*>(static_cast<void*>(&t_)) == pT
- 编译器如何实现__declspec(align(x)) / __attribute__(aligned(x)))?
- Azure Storage CPP & VCPKG
- C++应用程序缺少 winrt::Windows::Storage::Streams::D ataWriter
- thread_local "storage class specified"
- C++ 结构数组 - "This declaration has no storage class or type specifier"
- C++ 中的"this declaration has no storage class or type specifier"错误
- 如何修复派生类给出错误'declaration has no storage class or type specifier'?
- "declaration has no storage class or type specifier" C++
- 如何编译C 代码,包括Google Cloud Storage库
- 为什么对Aligned STD ::数组的初始自动矢量载荷是标量?(g /clang )
- C /WRL项目未知名称空间Windows :: Storage
- Marmalade Core Storage (s3eSecureStoragePut & s3eSecureStorageGet) not persisting
- 从 Windows::Storage::Streams::IBuffer 中获取字节数组
- 错误"this declaration has no storage class or type specifier"
- 使用字符串流时出现"Declaration has no storage class or type specifier"错误
- __attribute__((aligned(x)) 不适用于动态分配
- "storage-class information" __declspec() 是什么意思?
- ActiveMQ-CPP 在发送时抛出"Thread local storage limit"达到
- Including windows.storage.streams.h
- "Unrecognized storage class 111 for .text symbol `._XXXXXXXXX"是什么意思?