2013-04-22 72 views
10

我創建了一個父類來處理與智能指針Singleton模式創建sinlgeton類正確的做法:是否通過了weak_ptr

.h文件中:

template<class singleType> 
class Singleton 
{ 
public: 
    static std::shared_ptr<singleType> GetInstance(); 

private: 
    static std::weak_ptr<singleType> m_singleObject; 
}; 

.cpp文件:

template<class singleType> 
std::shared_ptr<singleType> Singleton<singleType>::GetInstance() 
{ 
    auto shareObject = m_singleObject.Lock(); 
    if (!shareObject) 
    { 
     shareObject.reset(new singleType); 
     m_singleObject = shareObject; 
    } 

    return shareObject; 
} 

不確定這是使用智能指針的正確方法嗎? 有什麼想法?

很多謝謝

+3

所以基本的想法是,一旦所有指向單例的指針超出了範圍,那麼單例就會被刪除。然後,當你需要一個指向單例的指針時,你又創建了一個新的單例?如果是這樣的話,它看起來不錯。還沒有嘗試過,但一切都看起來不錯。 – Danny 2013-04-22 05:57:34

+0

......我對單身人士的想象是在程序還活着的時候,他們不應該'刪除'。不是嗎? – deepmax 2013-04-22 06:02:47

+0

@MM。很多時候,是的。有時它也是「只能有一個,或者只有一個,但沒有更多。」 – WhozCraig 2013-04-22 06:08:01

回答

3

這個實現的優缺點已經討論過了。但是有一些bug:

1)因爲這是一個模板,你必須將你的實現移動到標題或鏈接器找不到它。

2)weak_ptr的.lock()函數不是大寫字母。

3)不要忘記實例

template<class singleType> 
std::weak_ptr<singleType> Singleton<singleType>::m_singleObject; 

4)更好地利用shareObject = std::make_shared<singleType>(singleType());代替new的:http://herbsutter.com/gotw/_103/

5)康拉德提到的:它不是線程安全的。

+0

感謝Gerrit,只有第2點,std :: weak_ptr函數是.Lock()。boost是.lock ()。 – 2013-04-22 12:51:15

+1

@MarkGuo我只用Clang和libC++試過。它的.lock()。並在這裏看到:http://en.cppreference.com/w/cpp/memory/weak_ptr – Gerrit 2013-04-22 18:47:58

1

據我所知,這應該沒問題。您將避免無序銷燬問題,但在創建初始實例後創建新實例可能會造成問題。這個單身人士在任何時候都只有一個實例存在,但是在整個程序運行過程中,運行多個實例可能總是存在。

這種破壞和娛樂在性能方面也可能是不必要的,不僅在副作用方面。

4

我做了一些研究,現在我會發佈一個答案。

該代碼看起來像它應該工作,並且是智能指針的正確用法。唯一的問題是你希望單身人士如何表現。這應該像一個單獨的課本行爲,除非目前沒有指向單例的指針,否則它會自行刪除。這種行爲真的取決於你的程序的實現。如果你希望singelton在它被使用時才存在,那麼我會說去做。

我只是避免創建和摧毀singelton太頻繁,特別是如果建設和解構特別密集。如果它不斷被創建和刪除,那麼你可能會更好地使用更加標準的單例實現。標準的單例行爲往往是單程序只在程序運行期間創建一次,並且永遠不會被刪除。

我認爲這是一個聰明的實現,因爲你有它的用處,我可能不得不借用這個想法。

+0

這是一個奇怪的想法,刪除,然後重新創建(如果需要)一個對象!它是不聰明的單身人士在第一個地方,但你試圖使它變得更糟。 – SChepurin 2013-04-22 06:14:21

+0

我不想爭論的優點單身人士,但我可以看到這種方法是有用的,特別是如果單身人士不經常使用,單身人士有特別大的記憶足跡。在很多情況下,他們是一個壞主意,但在其他人中,他們是非常有用的,難以編寫代碼 – Danny 2013-04-22 06:20:22

+0

這是一個單身測試代碼的問題,但是這個特殊的實現使得它幾乎不可能。 – SChepurin 2013-04-22 06:21:57

4

您的代碼不是線程安全的。

名稱lock可能暗示併發訪問被阻止,但事實上並沒有這樣的保證:當多個線程同時調用您的GetInstance函數時,您將獲得多個實例,而不是保證一個實例。

您需要爲整個GetInstance函數的生命週期創建一個明確的鎖。請注意,這當然不是非常有效。

+0

感謝Konrad,這是一個很好的觀點 – 2013-04-22 12:21:31