2016-11-04 53 views
3

我偶然發現了基於LLVM的Optional.h類的Optional<T>的實現,並且無法完全弄清楚它爲什麼按照它的方式實現。爲什麼LLVM的可選<T>以這種方式實現?

要儘量簡短,我只粘貼部分我不明白:

template <typename T> 
class Optional 
{ 
private: 
    inline void* getstg() const { return const_cast<void*>(reinterpret_cast<const void*>(&_stg)); } 
    typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type storage_type; 
    storage_type _stg; 
    bool _hasValue; 

public: 

    Optional(const T &y) : _hasValue(true) 
    { 
     new (getstg()) T(y); 
    } 

    T* Get() { return reinterpret_cast<T*>(getstg()); } 
} 

而且最幼稚的做法我能想到的:

template <typename T> 
class NaiveOptional 
{ 
private: 
    T* _value; 
    bool _hasValue; 

public: 
    NaiveOptional(const T &y) : _hasValue(true), _value(new T(y)) 
    { 
    } 

    T* Get() { return _value; } 
} 

問題:

  1. 如何解讀storage_type?作者的意圖是什麼?
  2. 這條線的語義是什麼:new (getstg()) T(y);
  3. 爲什麼不天真的實施工作(或者,有什麼利弊做了Optional<T>類有超過NaiveOptional<T>)?
+2

1)T對齊的內存(見[doc](http://en.cppreference.com/w/cpp/types/aligned_storage)),2)放置新的,3)可選的優點:你保存一個動態分配。 – Borgleader

+0

就#2而言:它被稱爲* placement new *,它基本上告訴'new'在先前分配的特定位置構造對象。 –

+0

P.S:在你的天真實現中,布爾值是多餘的,你可以比較nullptr來知道你是否有值。 – Borgleader

回答

6

簡短的回答是「表現」。

較長答案:

  1. storage_type提供一個內存區域,該區域的(a)足夠大,以適應類型T和(b)被正確地對準爲類型T.未對齊的存儲器訪問較慢。另請參閱doc
  2. new (getstg()) T(y)是新的展示位置。它不分配內存,而是在傳遞給它的內存區域中構造一個對象。 doc(所有形式的new - 搜索「放置新的」)。
  3. 天真的實現工作,但它有更糟糕的表現。它使用動態內存分配,這往往可能是一個瓶頸。 Optional<T>實現不使用動態內存分配(請參見上面的要點)。
-1

Std :: optional應該是從函數返回的。這意味着你將不得不將指針引用的內容存儲在某處。這不符合這個類別的目的

此外,你不能使用普通的T,因爲否則你將不得不以某種方式構造它。可選允許內容未初始化,某些類型不能默認構建。

爲了使類在支持的類型方面更加靈活,使用了一個擬合和正確對齊的存儲。只有在可選活動時,纔會構建真正的類型

你在想什麼可能是像std :: variant?

相關問題