2015-02-07 41 views
7

在一个变体类我工作的原始存储是一个字符数组:的reinterpret_cast/static_cast并未定义的行为

alignas(/* the strictest alignment of all types of the variant */) 
char storage[/* ... */]; 

赋值运算符是这样的:

template<class X> 
void operator=(const X &x) 
{ 
    // ...code for clearing the storage and setting the tag for type X... 

    new(storage) X(x); 
} 

而代码获取存储的对象是:

template<class X> 
const X &get() 
{ 
    // ... 
    return *reinterpret_cast<X *>(storage); 
    // ... 
} 

它似乎工作,但它总是很好的定义?我担心安全地取消引用指针(是否允许使用类型别名规则?)。

在当前实施和

return *static_cast<const X *>(static_cast<const void *>(storage)); 

相关问题/答案之间有什么不同之处:(见James Kanze的评论)

https://stackoverflow.com/a/7321815/3235496


编辑

第二个问题已经在这里有一个答案:C++ When should we prefer to use a two chained static_cast over reinterpret_cast

+0

当然这个'new(storage)X(x);'是内存泄漏 – 2015-02-07 12:51:21

+1

@EdHeal它通过放置new来在存储中构造X.对齐存储应该是安全的做法(例如http://stackoverflow.com/questions/4583125/char-array-as-storage-for-placement-new)。你能添加一些细节吗? – manlio 2015-02-07 13:00:39

回答

4

由于storage正确对齐,我无法想象其中的一个问题可能会出现。关于指针转换的段落(*)4.10说:类型为“指向cv T的指针”的prvalue,其中T是一个对象类型,可以转换为类型为“指向cv void的指针”的prvalue。将指针的非空指针值转换为对象类型为“指向cv void的指针”的结果表示与原始指针值相同的字节在内存中的地址。

关于您的第二个问题,请参阅第5.2.10段:对象指针可以显式转换为不同类型的对象指针。当对象指针类型的prvalue v转换为对象指针类型“指向cv T的指针”时,结果为static_cast<cv T*>(static_cast<cv void*>(v))其中cv代表可选constvolatile

所以这部分是保证每个规格。更因为我们看到,强制转换为void *应该指向的内存第一个字节,没有UB我的标准......提供的编译器的理解也同样理解;-)

(*)参考:Draft for current C++ specification