2017-01-09 59 views
0

在「選擇你的容器明智」的精神,我感興趣的是什麼存儲要麼只有一個沒有對象,例如在一個類中的成員的最佳途徑。例如,如果被保存的對象計算起來昂貴並且應該以某種方式緩存(或任何其他類型的「後期」創建),則可能是這種情況。在C++中存儲一個或沒有對象的首選方法是什麼?

的明顯的候選是std::vectorstd::unique_ptr,例如:

class object_t; 
class foo_t { 
    std::unique_ptr<object_t> m_cache; 
    public: 
    object_t getObject() { 
     if(not m_cache) { 
     m_cache.reset(new object_t()); // object creation is expensive 
     } 
     return object_t(*m_cache); 
    } 
}; 

和類似地用載體(或幾乎任何其它容器):

class object_t; 
class foo_t { 
    std::vector<object_t> m_cache; 
    public: 
    object_t getObject() { 
     if(m_cache.empty()) { 
     m_cache.push_back(object_t()); // object creation is expensive 
     } 
     return m_cache.front(); 
    } 
}; 

當然,還有這樣的可能性,以有一些布爾變量,其保持該物體的狀態:

class object_t; 
class foo_t { 
    bool cache_healthy; 
    object_t m_cache; 
    public: 
    foo_t() : cache_healthy(false), m_cache() {} 
    object_t getObject() { 
     if(not cache_healthy) { 
     m_cache = object_t(); 
     cache_healthy = true; 
     } 
     return m_cache; 
    } 
    /* do other things that might set cache_healthy to false. */ 
}; 

從三個例子,我喜歡最後一個少,因爲它要麼創建對象兩次,或者,如果我改變object_t有一個「廉價」的/不完整的構造,可能會返回一個無效的對象。

與我不喜歡更多語義,因爲一個矢量(或任何其它容器類型)可能給人的印象是有可能比只有一個對象的更多的載體中的溶液。

現在又想到它,我想我喜歡指針的解決方案,但是大多數仍然是不與它完全滿意,並想聽聽,如果你知道的任何解決方案,是最優雅的在這種情況下。

+3

'性病在1只2以及依賴副本不需要堆分配: :'或'boost.optional'。 –

+0

謝謝,我不知道那個功能。不過,它是C++ 17,但會牢記在心。 – jafasi

+1

我的解決方案使用'的std :: unique_ptr'似乎是最好的,'VECTOR'似乎很奇怪,這個目的 - 我會害怕某些應用中會使用非0初始大小。 object_t的想法會創建對象兩次 - 所以它不好 - 如果你的緩存有一些大的字段會怎麼樣。可選的解決方案 - 可能會被高度宣傳,但它最初使用緩存對象的大小 - 所以也許它不是這樣完美的解決方案 - 以防萬一你有很多緩存,並不是所有的緩存對象都被使用(並且對象非常大)。 – marcinj

回答

1

的 「明顯」 的解決方案是使用boost::optional或(在C++ 17)std::optional

的是這樣的實現可能如下所示:

template <typename T> 
class optional 
{ 
public: 
    optional() : m_isset(false) {} 

    template <typename ...Args> 
    optional(Args... args) { 
     m_isset = true; 
     new (&m_data[0]) optional { args... }; 
    } 

    // overload operator-> and operator* by reinterpret_casting m_data, throwing exceptions if isset == false 

private: 
    bool m_isset; 
    char m_data[sizeof(T)]; 
} 

您的解決方案的缺點是在3

+0

謝謝。我不知道那個C++ 17功能。 – jafasi

+1

事實上,新增功能是一個非常古老的功能,它在1998年標準化之前已經可用。 – filmor

相關問題