2017-10-15 83 views
-1

作爲一個例子,我們來談談使用new(在第一次調用getInstance()方法時創建實際實例,而不是使用靜態字段)的單例實現,它讓我明白永遠不會釋放內存。 。那就要做到這一點的應用程序關閉,以便系統能夠釋放該內存高達反正權利之前在程序結束之前不能釋放內存有多糟?

除了糟糕的設計,確實這種做法有什麼實際的缺點

編輯:廣告的評論 - 所有有效點? ,謝謝你們,所以讓我來問一下 - 對於單個線程應用程序和POD單例類,是否有任何實際的缺點?理論上講,我不打算真的這樣做。

+3

這是一個壞習慣,這是肯定的。除此之外,它確實取決於操作系統。一旦進程終止,大多數主要的PC操作系統都會釋放一個進程的所有資源。如果您在運行時使用泄漏檢測器查找內存泄漏,則在進程終止之前不釋放內存將導致誤報。 –

+3

取決於你是否擁有new'd可能擁有外部資源,而不僅僅是內存,例如。文件句柄等。您可能想要很好地關閉這些資源,而不是放棄它們。 –

+1

有一個原因,你應該總是使用'靜態'方法來處理單身:線程安全(在其他一些方面)... – Rakete1111

回答

0

對於單線程應用程序和POD單例類是否有任何實際的缺點?從理論上講,我不會那麼做。

standardese

[C++ 14 - 對象壽命-4]對於類型與非平凡的析構函數的目的,不要求該程序調用析構函數明確地前對象佔用的存儲空間被重用或釋放;但是,如果沒有顯式調用析構函數或者沒有使用delete-expression(5.3.5)釋放存儲,則不應該隱式調用析構函數,並且任何依賴析構函數產生的副作用的程序有未定義的行爲。

其中dtor在自動/靜態變量等隱式調用。因此,(假設一個新的表達式被用來構造對象)被調用的分配函數的運行時實現可以釋放內存並讓對象在遺忘時衰減,只要沒有可觀察的效果依賴於它的破壞(對於含有微不足道的類型的類型來說,這是非常正確的)。

+0

這並沒有說是否可以釋放存儲。 – rustyx

+0

@rustyx如果運行時在釋放內存時釋放內存我的答案表示沒有UB發生;如果運行時沒有,那麼會發生什麼是未定義的;) –

0

對所有單身類型使用schwartz計數器。這就是std::cout的實現方式。

優點:

  • 線程安全

  • 正確的初始化命令時,單身取決於對方

  • 正確的破壞順序在程序終止保證

  • 不使用堆

  • 100%符合C++ 98,C++ 03,C++ 11,C++ 14,C++ 17 ...

  • 不需要難看的getInstance()函數。只需使用全局對象。

https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter

至於標題問題:

如何壞右程序結束之前未釋放內存?

當程序在管理進程內存的操作系統下運行時,釋放內存並不是那麼糟糕。然而,單件做的其他事情可能包括沖洗IO緩衝區(例如std::cout,std::cerr)。這可能是你想避免丟失的東西。

+0

線程安全性如何? https://stackoverflow.com/questions/39393850/can-num-be-atomic-for-int-num – stark

+0

@stark因爲所有的單例都按正確的順序初始化,所以任何相關的線程都會發現它已經被初始化了。 –

+0

ok,但是屬於不同TU的有序初始化序列可以同時發生,是不是?...如果是,參考計數器訪問仍然應該同步 –