特殊類定制
在C++中,一些特殊性質的類如何設計
類禁止拷貝的對象
- C++11 使用delete關鍵字賦值給拷貝構造和賦值
- C++98將拷貝構造和賦值聲明在私有里
類只能在堆上創建的對象
- 將構造函數私有化, 提供一個獲取對象堆上創建對象的公有函數
- 將析構函數私有化, 提供一個釋放資源公有函數
類只能在棧上創建的對象
- 將構造函數私有化, 并提供一個獲取棧上創建的對象的公有函數
然后將operator new函數禁用掉, 但是無法防拷貝(有一定缺陷)
不能被繼承的類
- C++98將父類構造函數私有化
- C++11使用final關鍵字修飾父類
單例模式
一個類只能創建一個對象的類(singleton)
即只有唯一的實例對象
-
餓漢模式: 無論是否使用, 程序創建之前(main函數之前)就構造一個唯一的對象
- 先將構造函數私有化
- 使用私有的一個靜態的、對應類型的實例化對象成員, 在類內聲明, 類外初始化
- 提供一個靜態成員函數獲取到該對象
- 優點: 簡單, 無線程安全問題
- 缺點
- 單例模式多可能會導致進程的啟動慢
- 一個程序中, 有多個單例時, 無法控制其初始化的順序
-
懶漢模式: 第一次使用對象時再創建實例對象
-
設計方式同餓漢基本相同, 但調用靜態成員函數時(需要獲取實例對象時)再創建實例對象(new 實例對象)
-
優點對應著餓漢的缺點
- 可以控制多個單例的初始化順序
- 不影響啟動順序
-
缺點
-
線程安全問題
- 需要通過對應加鎖, 以及雙重判斷進行保護
static ThreadPool<T> *getIntance(int num = g_thread_num){// 雙重判斷, 減少反復的加鎖和解鎖操作(因為只有第一次調用該方法時才會有線程安全問題, 之后都不會)// 加多一個判斷, 后續再來的線程時, 則不需要再進行加解鎖, 只用做一次判斷即可(攔截了大量的無用的訪問鎖的行為->只有第一次訪問鎖有意義)if (pool == nullptr){LockGuard lock(&_smtx);if (pool == nullptr){pool = new ThreadPool<T>(num);}}return pool; }
-
-
-
單例對象的釋放問題
- 一般情況下, 單例對象在整個程序運行期間都需要使用, 所以一般都是不釋放的
單例對象在進程結束后也會進行資源釋放 - 一些特殊場景需要釋放, 如單例對象析構時, 需要進行一些持久化操作(往文件或者數據庫寫)
構建一個內嵌的垃圾回收類, 然后聲明一個全局的垃圾回收對象, 當單例對象生命周期到時, 則會自動析構該垃圾對象, 同時釋放單例對象資源
- 一般情況下, 單例對象在整個程序運行期間都需要使用, 所以一般都是不釋放的