2013-10-07 48 views
5

我使用std::aligned_storage作爲變體模板的後備存儲。問題是,一旦我在gcc上啓用了-O2,我開始收到警告'dereferencing type-punned pointer will break strict aliasing`。如何在使用aligned_storage時避免嚴格的混疊錯誤

真正的模板要複雜得多(類型在運行時檢查),但一個小例子,生成警告:

struct foo 
{ 
    std::aligned_storage<1024> data; 

    // ... set() uses placement new, stores type information etc ... 

    template <class T> 
    T& get() 
    { 
    return reinterpret_cast<T&>(data); // warning: breaks strict aliasing rules 
    } 
}; 

我敢肯定boost::variant基本上做同樣的事情,因爲這,但我似乎無法找到他們如何避免這個問題。

我的問題是:

  • 如果以這種方式使用aligned_storage違反嚴格走樣,我應該如何使用它?
  • 鑑於函數中沒有其他基於指針的操作,實際上是否存在嚴格別名問題get()
    • 如果get()已內聯,那麼該怎麼辦?
    • get() = 4; get() = 3.2怎麼樣?由於intfloat是不同的類型,該序列是否可以重新排序?
+0

不對齊以任何方式影響的別名問題?希望它是原因的一部分(但是這並不會改變標準對它的態度,doens't?) – dhein

+0

@Zaibis不,使用'aligned_storage'而不是任何其他類型作爲緩衝區shouldn'沒有任何區別。我在這裏指定'aligned_storage'的原因是,它似乎是爲了這種用途而設計的。 – marack

+0

@marack:你不應該(並且不允許)直接使用'aligned_storage'。我編輯了我的答案,試圖使(更)更清楚。 – rici

回答

5

std::aligned_storage<type_traits>一部分;像該頭文件中其他居民的大部分一樣,它只是一些typedef的持有者,並不意味着被用作數據類型。它的工作是採取尺寸和對齊方式,並使您成爲具有這些特徵的POD類型。您可以直接使用std::aligned_storage<Len, Align>。您必須使用std::aligned_storage<Len, Align>::type轉換後的類型,它是「POD類型,適合用作任何大小最大爲Len,對齊度爲Align的除數的對象的未初始化存儲。」 (Align默認爲最大有用對準大於或等於Len。)

作爲C++標準音符,通常的類型由std::aligned_storage返回將是unsigned char的陣列(指定大小的)具有對準說明符。這避免了「無嚴格別名」規則,因爲字符類型可能會與別的類型相混淆。

所以,你可能做這樣的事情:

template<typename T> 
using raw_memory = typename std::aligned_storage<sizeof(T), 
               std::alignment_of<T>::value>::type; 

template<typename T> 
void* allocate() { return static_cast<void*>(new raw_memory<T>); } 

template<typename T, typename ...Arg> 
T* maker(Arg&&...arg) { 
    return new(allocate<T>()) T(std::forward<Arg>(arg)...); 
} 
+0

啊,謝謝。我沒有意識到'aligned_storage'是暴露類型的特徵,而不是類型本身。正如你所提到的,使用'aligned_storage <...> :: type'可以正確解決嚴格的別名問題。 – marack

+4

這種情況是*其他類型*別名字符類型。嚴格的別名規則不是對稱的,它禁止*其他類型*別名字符類型,但它允許字符類型別名*其他類型*(這裏沒有發生)。然而,[這個答案](http://stackoverflow.com/questions/13466556/aligned-storage-and-strict-aliasing)認爲''aligned_storage'不會因爲其他原因違反嚴格的別名(儘管我不太關注它的論點)。 –

相關問題