2016-11-04 52 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?

相关问题