關於C 單例模式記憶體釋放問題的一點點總結

2021-08-21 17:38:11 字數 2452 閱讀 7061

寫在最後面

網路上有很多關於c++單例模式的帖子,其中不乏精品之作。本篇文字在吸收了精華之餘,僅作了個人的一點點總結。

通過new出乙個物件來實現的單例,不論單例是通過餓漢方式,還是懶漢方式來實現,都面臨乙個問題,即new出來的物件由誰釋放,何時釋放,怎麼釋放 ?簡單的實現可以參考c++ 單例模式

如果物件沒有被釋放,在執行期間可能會存在記憶體洩露問題。有人可能會說,在程序結束時,作業系統會進行必要的清理工作,包括釋放程序的所有堆疊等資訊,即使存在記憶體洩露,作業系統也會收回的;且對於單例來講,程序執行期間僅有乙個物件例項,而且該例項有可能根本就沒有進行記憶體的申請操作,不釋放例項所佔記憶體,對程序的執行也不會造成影響。這麼說好像很有道理的樣子,既然作業系統會清理一切後續工作,那麼我們還有必要進行記憶體釋放工作嗎?

閒話少敘,言歸正傳。作為乙個非著名的程式猿,我和大多數同類一樣,對**有著不一般的情結,且有強迫症。成對的使用new和delete是程式猿們最基礎的素養。這麼看來,單例物件的釋放必須要在**中體現出來。

很自然的,可能會有部分猿/媴們[其實就是我啦^-^]想到,把釋放工作交給析構函式來處理不就行了。想法是不錯,**要怎麼寫吶?可能如下:

~dtor()

可惜的是,一:new出來的物件,必須用與之對應的delete顯示的來釋放,程式並不會自動呼叫析構函式來析構new出來的物件;二:在delete的時候會呼叫析構函式,析構函式中又呼叫了delete,然後又呼叫了析構函式……這樣就進入了乙個無限的迴圈之中。

可能的**:

int main(int argc, char ** argv)

valgrind檢測結果

通過valgrind工具,我們可以看到,所有記憶體都被釋放了。這種處理完成了任務,好像無可厚非。但是,大多數情況下,這條語句會被遺忘,如果程式中存在多個單例,也很容易將某個物件的釋放操作遺漏。

atexit()函式可以用來註冊終止函式。如果打算在main()結束後執行某些操作,可以使用該函式來註冊相關函式。

可能的**:

void del_singleton_01()

}int main(int argc, char **argv)

valgrind檢測結果

標準規定atexit()至少可以註冊32個終止函式,如果系統中有多個單例,我們可能要註冊多個函式,或者在同乙個終止函式中釋放所有單例物件。但是方式一中的問題依然存在。必須由程式猿/媴手工註冊,且有可能遺漏某個物件。

本方式由單例類提供乙個釋放物件的函式,在該函式內部進行物件的釋放操作。其本質與方式一併無太大差別,同樣的繼承了方式一的缺點。

可能的**:

class singleton 

}// ...

};int main(int argc, char ** argv)

雖然這是一種可行的釋放物件方式,但是這種方式並沒有明顯的優點。這不是我們想要的方案。

我們知道,程序結束時,靜態物件的生命週期隨之結束,其析構函式會被呼叫來釋放物件。因此,我們可以利用這一特性,在單例類中宣告乙個內嵌類,該類的析構函式專門用來釋放new出來的單例物件,並宣告乙個該類型別的static物件。

可能的**:

class singleton }};

static garbagecollector gc;

};// 定義

singleton::garbargecollector singleton::gc;

// ...

valgrind檢測結果:

好了,我們可以像之前一樣使用單例了,不需要再關心物件的釋放問題。程序結束時,作業系統會幫我們去釋放的。

之所以要進行記憶體的釋放,是因為在單例的實現過程中,我們使用了new來建立物件。如果在實現過程中,不使用new,而是使用靜態[區域性]物件的方式,就不存在釋放物件的問題了。

可能的關鍵**:

class singleton ;

// ...

singleton singleton::instance;

// ...

或者

class singleton ;

singleton & singleton::get_instance()

單例模式的記憶體釋放

單例模式前面已經說過了,下面說說單例模式的私有靜態成員 singleton的釋放 如果在類的析構行為中有必須的操作,比如關閉檔案,釋放外部資源,那麼上面所示的 無法實現這個要求。我們需要一種方法,正常地刪除該例項。可以在程式結束時呼叫getinstance並對返回的指標呼叫delete操作。這樣做可...

C 單例模式物件釋放的問題

std mutex resource mutex class mycas 這是乙個單例類 私有化建構函式 private static mycas m instance 靜態成員變數 public static mycas getinstance return m instance class cg...

c 單例模式的自動釋放問題

1.巢狀類 靜態物件 include using std cout using std endl class singleton return pinstance private class autorelease autorelease private singleton singleton pr...