最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++深入詳解單例模式與特殊類設計的實現(xiàn)

 更新時間:2022年06月13日 14:27:47   作者:你算哪一個bug?  
這篇文章主要為大家詳細介紹了C++單例模式和特殊類的設計,單例模式這種類型的設計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

單例模式

什么是單例模式

單例模式(Singleton),保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。–大話設計模式

應用場景

保證一個類只有一個實例

  • 如Windows下的任務管理器,回收站等。
  • 日志管理,計數(shù)器等。

簡而言之,你需要唯一實例時就可以考慮單例模式。這樣它可以嚴格地控制客戶怎樣訪問即何時訪問它,即對唯一實例的受控訪問。

優(yōu)缺點

優(yōu)點

  • 減少內存開銷,因為在系統(tǒng)中只有一個實例。
  • 避免了頻繁的創(chuàng)建和銷毀對象,提高了性能
  • 避免對資源的多重占用,比如單例時多人只寫一個日志文件,如果有多個日志文件可能導致對相同的日志文件進行寫操作
  • 設置全局訪問點

缺點

  • 職責過重,與單一職責存在沖突
  • 不能繼承(構造方法私有)

實現(xiàn)

單例模式有兩種實現(xiàn)模式,懶漢模式和餓漢模式。

注意單例模式的概念,大概就是唯一實例且有全局訪問點,我們從這兩點入手。

唯一實例:構造函數(shù)私有+防拷貝

拷貝構造是一種構造方式,所以需要防止,構造函數(shù)私有不讓別人new。

全局訪問點:給一個公共的接口

餓漢模式

簡單來說,把東西一開始就做好,需要的時候直接吃。

#include <iostream>
using namespace std;
class Singleton
{
public:
	static Singleton& GetInstance()
	{
		return _instance;
	}
	int GetRandom()//由于側重點不是隨機數(shù) 所以直接返回一個30
	{
		return 30;
	}
private:
	Singleton() {}//構造函數(shù)私有
	Singleton(Singleton&) = delete;//防拷貝,被=delete修飾表明這個函數(shù)被刪除,即可以只聲明不實現(xiàn),換言之禁用了該函數(shù)
	Singleton& operator=(const Singleton&) = delete;//防拷貝
	static Singleton _instance;
};
Singleton Singleton::_instance;//類外必須初始化,類內只是聲明
int main()
{
	//1.調用
	cout<<Singleton::GetInstance().GetRandom()<<endl;
	//2.
	Singleton& s = Singleton::GetInstance();
	cout<<s.GetRandom()<<endl;
	return 0;
}

通過防拷貝和構造函數(shù)私有化之后下面的幾種辦法都失效了

Singleton s;//err
Singleton s1(s);//err
Singleton s1=s;//err

從上面我們可以看出餓漢模式的優(yōu)缺點了,有點顯而易見就是實現(xiàn)很簡單粗暴,缺點很明顯,類加載時單例對象就已經生成了,即還沒有用就已經加載出來了,比如這個資源很大,又在游戲啟動時加載,那就會造成游戲啟動很慢。且如果有多個單例對象啟動時實例化順序不確定(不同源文件類內的單例對象實例化順序是不確定的,懶漢模式解決了這個問題,因為懶漢模式的實例化在函數(shù)內部,可以通過調用函數(shù)的順序來解決實例化的順序問題)。

類加載時靜態(tài)初始化解決了線程安全問題。

懶漢模式

什么時候需要就什么時候做飯,然后吃。

class Singleton
{
public:
	static Singleton* GetInstance()
	{
		if (_instance == nullptr)
		{
			_mtx.lock();//double lock保證線程安全
			if (_instance == nullptr)//必須再次檢查  不然可能另一個線程那已經new完了,這邊又new違背了單例,且可能覆蓋數(shù)據(jù)。
			{
				_instance = new Singleton();
			}
			_mtx.unlock();
		}
		return _instance;
	}
	int GetRandom()
	{
		return 30;
	}
	class Clear//資源回收的內部類,必須是公有的,不然外部聲明報錯
	{
	public:
		~Clear()
		{
			cout << "釋放資源" << endl;
			delete _instance;
		}
	};
private:
	static Clear _cle;
	Singleton() {}
	Singleton(Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
	static Singleton* _instance;
	static mutex _mtx;//線程安全
};
Singleton* Singleton::_instance = nullptr;
mutex Singleton::_mtx;
Singleton::Clear _cle;
int main()
{	
	//1.
	cout<<Singleton::GetInstance()->GetRandom()<<endl;
	//2/
	static Singleton* s = Singleton::GetInstance();
	cout << s->GetRandom() << endl;
	//不能用左值引用接收的原因  返回值是右值 得用右值引用接收
	//為什么函數(shù)返回值是右值  因為返回值是借助臨時變量返回的拿不到地址
	//如果返回值是左值引用就能用左值引用接收
	return 0;
}

懶漢模式的優(yōu)缺點也很明顯,優(yōu)點是什么時候第一次用就什么時候實例化,此外可以通過調用函數(shù)解決多個單例對象實例化的順序問題,缺點就是寫起來復雜,要考慮線程安全和內存泄露方面的問題。懶漢采用的是指針也更好回收資源(餓漢采用的是對象)

懶漢可能因為多線程丟數(shù)據(jù),線程加鎖保證在多線程環(huán)境下一定只有一個線程去new對象,只創(chuàng)建出一個單例對象,加鎖可能導致頻繁切換上下文,double lock解決。

特殊類設計

我們一般會通過構造函數(shù),拷貝構造和賦值重載創(chuàng)建對象,現(xiàn)在把這幾種方法全禁用了,然后自己再寫一個外部可調用的接口來自定義類的創(chuàng)建方式。

當然也有別的辦法,這種經常可以作為一種通解思路。

下面的禁用采用C++11的delete關鍵字實現(xiàn),作用是禁止編譯器生成默認的函數(shù)版本,即有聲明但無實現(xiàn)。

設計一個類只能在堆上創(chuàng)建對象

簡單來說只能通過new來創(chuàng)建對象。

方法一

構造方法禁用,然后給一個接口讓外部調用。

構造方法的禁用=構造函數(shù)私有+禁用拷貝構造+禁用賦值重載

class HeapOnly
{
public:
	static HeapOnly* GetInstance()
	{
		return new HeapOnly;
	}
	void Test()
	{
		cout << "I am Test" << endl;
	}
private:
	HeapOnly() {}
	HeapOnly(HeapOnly&) = delete;
	HeapOnly& operator=(const HeapOnly&) = delete;
};
int main()
{	
	HeapOnly* ho = HeapOnly::GetInstance();
	ho->Test();
	delete ho;
	return 0;
}

方法二

析構函數(shù)私有

對象建立在棧上,是由編譯器分配空間的,編譯器管理對象的生命周期,對象使用完后編譯器會檢查這個對象所有的非靜態(tài)函數(shù),包括析構函數(shù),當編譯器發(fā)現(xiàn)析構函數(shù)不能訪問后就不能回收這塊空間,所以編譯器無法為其分配空間,編譯器檢查到這種情況也會報錯。

析構函數(shù)私有的方法不建議使用,因為在類外無法使用delete釋放空間,容易造成內存泄漏。

class HeapOnly
{
public:
	void Test()
	{
		cout << "I am Test" << endl;
	}
private:
	~HeapOnly();
};
int main()
{	
	//HeapOnly ho_stack;//err
	HeapOnly* ho = new HeapOnly;
	ho->Test();
	return 0;
}

只能在棧上創(chuàng)建對象

方法一

不能使用new --> 重載operator new即可。

這種存在一個缺陷,就是仍然可以在靜態(tài)區(qū)創(chuàng)建對象

方法二

將構造函數(shù)設為私有再自定義一個接口

這里不用禁用構造函數(shù),拷貝構造,賦值重載,因為對于下面的場景來說,匿名對象的拷貝構造更符合場景,編譯器會選拷貝構造來進行構造,所以如果我們禁用了拷貝構造會報錯,因為我們的delete關鍵字是有聲明無實現(xiàn),并不是真的把這個函數(shù)連帶聲明刪除了。所以StackOnly()一看有我們自己寫的拷貝構造的聲明就會去匹配這個拷貝構造,我們自己寫的拷貝構造又沒有實現(xiàn)拷貝功能就會報錯。

理解這個和編譯鏈接知識有關,編譯器看到聲明就去匹配了,而不是一定要看到函數(shù)實現(xiàn)才匹配,鏈接時候才會去找實現(xiàn),當發(fā)現(xiàn)有聲明無實現(xiàn)時就很容易導致鏈接錯誤。

一個類不能被繼承

父類構造函數(shù)私有即可,構造時先構造父類再構造子類,父類構造不出不能繼承。

最后

關于單例模式,可以說是只能創(chuàng)建一個對象的實現(xiàn)。

還有個小問題,為什么不用全局變量代替單例模式,全局定義一個唯一的變量不就行了,合理吧[doge],理論上可以,但是非常不建議,可以自行查找資料"為什么不建議使用全局變量"。

全局變量的使用可能帶來很多問題,而且很容易造成鏈接、重定義等錯誤,如果多人協(xié)作時有人再給這個變量起個別名,那維護代碼時代價就太大了,這還只是全局變量的一個小缺點。

??痛a規(guī)范評分里也不建議用全局變量,當然寫題時代碼沒那么長,幾個全局變量倒時不打緊。

.h不能包含定義,不然多個cpp去包含就會有鏈接錯誤,盡量把定義和聲明分離開來

【82】【Cherno C++】【中字】C++的單例模式_嗶哩嗶哩_bilibili

Github代碼匯總

到此這篇關于C++深入詳解單例模式與特殊類設計的實現(xiàn)的文章就介紹到這了,更多相關C++單例模式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C/C++中static,const,inline三種關鍵字詳細總結

    C/C++中static,const,inline三種關鍵字詳細總結

    以下是對C/C++中static,const,inline的三種關鍵字進行了詳細的分析介紹,需要的朋友可以過來參考下
    2013-09-09
  • Qt地圖自適應拉伸的實現(xiàn)示例

    Qt地圖自適應拉伸的實現(xiàn)示例

    最近需要寫一個程序,要是讓qt到程序自適應,本文主要介紹了Qt地圖自適應拉伸的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • c語言重要的字符串與內存函數(shù)

    c語言重要的字符串與內存函數(shù)

    這篇文章主要介紹一些c語言中常用字符串函數(shù)和內存函數(shù)的使用和注意事項,并且為了幫助讀者理解和使用,也都模擬實現(xiàn)了他們的代碼,需要的朋友可以參考一下
    2021-09-09
  • C++ 中消息隊列函數(shù)實例詳解

    C++ 中消息隊列函數(shù)實例詳解

    這篇文章主要介紹了C++ 中消息隊列函數(shù)實例詳解的相關資料,需要的朋友可以參考下
    2017-06-06
  • 基于QT實現(xiàn)自定義溫度計的示例代碼

    基于QT實現(xiàn)自定義溫度計的示例代碼

    QT原生控件沒有實現(xiàn)如儀表盤或者溫度計的控件,只好自己實現(xiàn),所以本文為大家介紹了如何利用qt實現(xiàn)自定義溫度/濕度控件,感興趣的小伙伴可以了解下
    2023-11-11
  • 圖解AVL樹數(shù)據(jù)結構輸入與輸出及實現(xiàn)示例

    圖解AVL樹數(shù)據(jù)結構輸入與輸出及實現(xiàn)示例

    這篇文章主要為大家介紹了C++圖解AVL樹數(shù)據(jù)結構輸入與輸出操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05
  • c語言中的文件加密與解密

    c語言中的文件加密與解密

    這篇文章主要介紹了c語言中的文件加密與解密方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Linux系統(tǒng)下如何使用C++解析json文件詳解

    Linux系統(tǒng)下如何使用C++解析json文件詳解

    JSON(JavaScript Object Notation, JS 對象簡譜) 是一種輕量級的數(shù)據(jù)交換格式。下面這篇文章主要給大家介紹了關于Linux系統(tǒng)下如何使用C++解析json文件的相關資料,需要的朋友可以參考下
    2021-06-06
  • C++共享內存刪除的陷阱

    C++共享內存刪除的陷阱

    這篇文章主要介紹了C++共享內存刪除的陷阱講解,當進程結束使用共享內存區(qū)時,要通過函數(shù) shmdt 斷開與共享內存區(qū)的連接。下面來看看具體問題都是怎么解決的吧
    2022-01-01
  • C++中順序表操作的示例代碼

    C++中順序表操作的示例代碼

    這篇文章主要為大家詳細介紹了C++中順序表的基礎操作的相關代碼,主要有順序表的輸出、插入和刪除數(shù)據(jù)等,感興趣的小伙伴可以了解一下
    2022-10-10

最新評論

九江县| 同德县| 勐海县| 乌海市| 南靖县| 嘉义县| 庆云县| 宣化县| 雅安市| 阜宁县| 六枝特区| 铜梁县| 通州市| 蒙阴县| 海南省| 堆龙德庆县| 阜新| 绍兴县| 武山县| 泗阳县| 余江县| 德州市| 绩溪县| 蚌埠市| 新安县| 龙泉市| 枣强县| 临泽县| 兖州市| 长沙市| 林州市| 安徽省| 历史| 达孜县| 三穗县| 丰城市| 黄大仙区| 远安县| 工布江达县| 仙游县| 阳高县|