2015-02-07 87 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