我目前使用aligned_storage来实现类似的boost ::可选的“可选”类型。 要做到这一点我有一个类的成员,如下所示:
typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type t_;
我用放置新创建的对象,但我不存储任何地方返回的指针。 相反,我(通过布尔标志也存储在我的可选类型显然与检查,以确保对象是有效的)访问底层的类型在这样我所有的成员函数的对象:
T const* operator->() const {
return static_cast<T const*>(static_cast<void const*>(&t_));
}
我的问题是,这是否是安全的。 我的理解是,我放置新的使用改变了对象的“动态式”,只要我继续使用这种类型的访问存储器我会好起来的。 不过我不是我是否必须持有由安置新的还是我允许只投为基础类型,每当我需要访问它返回的指针清晰。 我已阅读C ++ 11标准的3.10节,但是我没有足够的standardese流利是肯定的。
如果可能的话,我会觉得更好,如果你能给参考答案标准(它帮助我在晚上睡觉:P)。
ABICT您的使用是安全的。
§5.3.4/ 10说:
一种新的表达通过的空间要求的分配的功能类型的std的第一个参数::为size_t量。 这样的说法应不低于要创建的对象的大小更小; 不是被创建的对象的大小仅当对象是一个数组它可以更大。
对于非阵列对象,分配的大小不能大于所述对象的大小,所以对象表示必须以适合于所分配的存储器的开始处开始。
放置新返回指针中传递(见第18.6.1.3/2)作为“分配”的结果,所以构造的对象的对象表示将在该地址开始。
-
static_cast<>
和之间的隐式转换T*
类型和void*
的指针对象的指针和指向它的存储之间进行转换,如果对象是一个完整的对象。
§4.10/ 2说:
类型“指向cv T,”,其中T是一个对象类型的prvalue,可以转换为类型“指向cv空隙”的prvalue。 一“指向cv T”转换为“指向cv空隙”指向其中类型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空隙”的prvalue可以转换为类型的“指针CV2 T,”,其中T是一个对象类型和CV2是相同的CV-资格,或更大的CV-资格比,CV1一个prvalue。 [...]类型的指针的值,以对象转换为“指向cv空隙”和背部,可能具有不同的CV-资格,应具有其原始值。
所以,如果你有一个void*
指向的存储T
对象(也就是指针值会导致一个的隐式转换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