2017-02-17 37 views
2

因此,我構建了一個類,我打算使用std::aligned_storage來爲「變體」類存儲最多16個字節的不同類型。理論上它應該能夠存儲任何POD類型和普通容器,例如std::stringstd::map如何破壞通過「安置新」構建的無析者類型

我經過這裏找到的代碼示例,它看起來就像是爲正是我一直在尋找製作:http://en.cppreference.com/w/cpp/types/aligned_storage

我的版本,基本上是:

class Variant { 
public: 
    Variant() { /* construct */ } 
    Variant(std::map<int,int> v) { 
     new(&m_data) std::map<int,int>(v); // construct std::map<int,int> at &m_data 
     m_type = TYPE_MAP; 
    } 
    ~Variant() { 
     if (m_type == TYPE_MAP) { 
      // cool, now destruct..? 
      reinterpret_cast<std::map<int, int>*>(&m_data)->~/*???????????????*/(); 
     } 
    } 

private: 
    // type of object in m_data 
    enum Type m_type; 
    // chunk of space for allocating to 
    std::aligned_storage<16, std::alignment_of<std::max_align_t>::value>::type m_data; 
}; 

我的問題自帶破壞。正如你可以在/*???????????????*/看,我不知道該怎麼代替~T()在cppreference.com例如撥打電話:

reinterpret_cast<const T*>(data+pos)->~T(); // I did the same thing except I know what T is, is that a problem is it? 

在我心中,我在做同樣的事情,無論模板匿名。問題是,std::map沒有任何std::map::~map()析構方法,只有一個std::map::~_Tree,這顯然不打算直接使用。因此,在cppreference.com示例代碼中,如果Tstd::map<int,int>~T()會調用什麼,以及我如何調用std::aligned_storage中已知類型的對象的析構函數的正確方法是什麼?還是我過於複雜的事情,並保證這些STL容器中的方法能保證等價於完全銷燬?

或者,有沒有更簡單的方法呢?由於我對std::aligned_storage的預期用法可能誤解了一些內容。

+4

是什麼讓你覺得沒有'std :: map ::〜map()'?當然有。 – Brian

+0

啊,我要問的是,這與我的編譯器有什麼特別的關係,但是一定要編輯它。那麼,我在看Visual Studio 2015對C++ 11的支持嗎?因爲頭文件中幾乎肯定沒有...... @Brian – Deji

+2

所有類都有析構函數(編譯器隱式聲明,如果不這樣做),還可以在非類類型上使用'〜T()'語法它被定義爲不可操作 –

回答

5

這聽起來像您已經閱讀其中std::map定義,並認爲std::map沒有析構函數,因爲頭文件較大你找不到析構函數的聲明。

但是,在C++中,沒有聲明析構函數的類型將具有編譯器聲明的隱含的聲明。這個隱式析構函數會調用基類和非靜態成員的析構函數。聽起來像你的庫實現中的std::map是一個超過_Tree的薄層。因此,摧毀地圖需要做的就是摧毀樹。因此,編譯器的默認析構函數會執行這個技巧。

允許在你的情況下編寫->~map(),它會調用隱式定義的析構函數,並且地圖將被正確銷燬。您也可以使用這種語法與標量類型,如int(但不是數組,出於某種原因)。

+0

啊,所以我只是因爲缺乏Visual Studio的Intellisense建議和頭文件本身的存在而過早地推遲了。我想我只是認爲某些對象的_explicit_銷燬有某些特定的錯誤。 D'哦! – Deji

2

我不知道到位的~T()

你的類型,它被命名爲map什麼叫:

reinterpret_cast<std::map<int, int>*>(&m_data)->~map(); 

如果它讓你感覺更好,你可以把功能模板:

template <class T> 
void destroy_as(void* p) { 
    static_cast<T*>(p)->~T(); 
} 

destroy_as<std::map<int, int>>(&m_data); 

問題是,std::map沒有任何std::map::~map()析方法

它可以產生編譯器,但類型可靠具有析構函數。所有類型都有析構函數。有些可能明確或實施deleted,但它們存在。


請注意,您aligned_storage太小,無法存儲mapsizeof(std::map)比16

+0

它在Visual Studios實現中似乎是12,我並不感到驚訝,它並不是全部相同。我使用'std :: string'(因爲它具有'std :: string ::〜basic_string()')的源代碼調整了我的示例,使情況變得不那麼明顯)。我也計劃添加'std:map'支持,所以這讓我想起我需要在繼續之前檢查更深層次,謝謝。 – Deji