国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

網(wǎng)站開發(fā)難嗎200891

網(wǎng)站開發(fā)難嗎2008,91,phpcms網(wǎng)站title,廣州新冠疫情最新公布一、請(qǐng)?jiān)O(shè)計(jì)一個(gè)類,不能被拷貝 拷貝只會(huì)放生在兩個(gè)場(chǎng)景中:拷貝構(gòu)造函數(shù)以及賦值運(yùn)算符重載,因此想要讓一個(gè)類禁止拷貝, 只需讓該類不能調(diào)用拷貝構(gòu)造函數(shù)以及賦值運(yùn)算符重載即可。 C98 將拷貝構(gòu)造函數(shù)與賦值運(yùn)算符重載只聲明不定義…

一、請(qǐng)?jiān)O(shè)計(jì)一個(gè)類,不能被拷貝

拷貝只會(huì)放生在兩個(gè)場(chǎng)景中:拷貝構(gòu)造函數(shù)以及賦值運(yùn)算符重載,因此想要讓一個(gè)類禁止拷貝,
只需讓該類不能調(diào)用拷貝構(gòu)造函數(shù)以及賦值運(yùn)算符重載即可。

  • C++98

????????將拷貝構(gòu)造函數(shù)與賦值運(yùn)算符重載只聲明不定義,并且將其訪問權(quán)限設(shè)置為私有即可。

class CopyBan
{// ...private:CopyBan(const CopyBan&);CopyBan& operator=(const CopyBan&);//...
};

原因:
????????1. 設(shè)置成私有:如果只聲明沒有設(shè)置成private,用戶自己如果在類外定義了,就可以不能禁止拷貝了
????????2. 只聲明不定義:不定義是因?yàn)樵摵瘮?shù)根本不會(huì)調(diào)用,定義了其實(shí)也沒有什么意義,不寫
反而還簡(jiǎn)單,而且如果定義了就不會(huì)防止成員函數(shù)內(nèi)部拷貝了。

  • C++11

????????C++11擴(kuò)展delete的用法,delete除了釋放new申請(qǐng)的資源外,如果在默認(rèn)成員函數(shù)后跟上
=delete,表示讓編譯器刪除掉該默認(rèn)成員函數(shù)。

class CopyBan
{// ...CopyBan(const CopyBan&)=delete;CopyBan& operator=(const CopyBan&)=delete;//...
};

二、請(qǐng)?jiān)O(shè)計(jì)一個(gè)類,只能在堆上創(chuàng)建對(duì)象

方法一:將類的析構(gòu)函數(shù)私有。防止別人調(diào)用拷貝在棧上生成對(duì)象

編譯報(bào)錯(cuò):

棧上創(chuàng)建會(huì)自動(dòng)調(diào)用析構(gòu),這里析構(gòu)被私有了,就不能在棧上創(chuàng)建。

但這樣在堆上創(chuàng)建后要進(jìn)行delete也要調(diào)用析構(gòu)函數(shù)也就是雖然不能在棧上創(chuàng)建對(duì)象,但是同樣也不能在堆上創(chuàng)建對(duì)象了。

解決方法:在類public中實(shí)現(xiàn)一個(gè)成員函數(shù)進(jìn)行delete

class HeapOnly
{
public:void Destroy(){delete this;}
private:~HeapOnly(){//...}
};int main()
{//HeapOnly hp1;//static HeapOnly hp2;HeapOnly* hp3 = new HeapOnly;//delete hp3;hp3->Destroy();return 0;
}

編譯成功:

方法二:

實(shí)現(xiàn)方式:
1. 將類的構(gòu)造函數(shù)私有,拷貝構(gòu)造聲明成私有。防止別人調(diào)用拷貝在棧上生成對(duì)象。
2. 提供一個(gè)靜態(tài)的成員函數(shù),在該靜態(tài)成員函數(shù)中完成堆對(duì)象的創(chuàng)建。

完整代碼:

class HeapOnly
{
public:static HeapOnly* CreateObj(){return new HeapOnly;}
private:HeapOnly(){//...}HeapOnly(const HeapOnly& hp) = delete;HeapOnly& operator=(const HeapOnly& hp) = delete;
};int main()
{HeapOnly* hp3 = HeapOnly::CreateObj();//HeapOnly copy(*hp3);return 0;
}

以上代碼有兩個(gè)細(xì)節(jié):

1. 如果沒有提供靜態(tài)的成員函數(shù):

會(huì)發(fā)生報(bào)錯(cuò),調(diào)用一個(gè)類的普通成員函數(shù)是不是需要對(duì)象去調(diào)用,那我們?cè)诙焉仙暾?qǐng)的對(duì)象又正好需要調(diào)用這個(gè)函數(shù)來生成,可是我們選擇都沒有對(duì)象我們?nèi)绾稳フ{(diào)用這個(gè)函數(shù)呢?所以這就純純是先有雞還是先有蛋的問題了。

為了解決這個(gè)問題,我們可以將這個(gè)成員函數(shù)設(shè)置成靜態(tài)的。

2. 利用拷貝構(gòu)造在棧上創(chuàng)建報(bào)錯(cuò):

雖然我們不能夠直接的在棧上創(chuàng)建對(duì)象,但是我們可以在堆上申請(qǐng)一個(gè)對(duì)象之后再調(diào)用一次拷貝構(gòu)造然后間接的就在棧上申請(qǐng)對(duì)象了。

所以我們的完整代碼還要將拷貝構(gòu)造和賦值重載都聲明成delete禁掉,所以這里調(diào)用拷貝構(gòu)造報(bào)錯(cuò)

三、請(qǐng)?jiān)O(shè)計(jì)一個(gè)類,只能在棧上創(chuàng)建對(duì)象

方法:同上將構(gòu)造函數(shù)私有化,然后設(shè)計(jì)靜態(tài)方法創(chuàng)建對(duì)象返回即可。

下面先來看這種方式的實(shí)現(xiàn):

編譯報(bào)錯(cuò),說明不能在堆上創(chuàng)建。

但是我們?nèi)绻趎ew的時(shí)候調(diào)用拷貝構(gòu)造:

編譯通過:

我們發(fā)現(xiàn)又可以在堆上成功了,說明這種方法還有漏洞。

解決方法:下面我們來分析一下:new是由operator new + 構(gòu)造組成的,所以我們只要在類中重載一個(gè)new,并將new聲明成delete,就可以解決這個(gè)問題。

class StackOnly
{
public:static StackOnly CreateObj(){StackOnly st;return st;}
private:StackOnly(){//...}// 對(duì)一個(gè)類實(shí)現(xiàn)專屬operator newvoid* operator new(size_t size) = delete;
};

運(yùn)行發(fā)現(xiàn)報(bào)錯(cuò),說明不能只有new在堆上創(chuàng)建對(duì)象了。

四、請(qǐng)?jiān)O(shè)計(jì)一個(gè)類,不能被繼承

  • C++98方式

將構(gòu)造函數(shù)私有:

基類的私有成員在派生類不可訪問,而派生類要繼承,需要調(diào)用基類的構(gòu)造函數(shù)。所以將構(gòu)造函數(shù)私有可以,讓類不能被繼承。

// C++98中構(gòu)造函數(shù)私有化,派生類中調(diào)不到基類的構(gòu)造函數(shù)。則無法繼承
class NonInherit
{
public:static NonInherit GetInstance(){return NonInherit();}
private:NonInherit(){}
};
  • C++11方法

final關(guān)鍵字,final修飾類,表示該類不能被繼承。

class A ?final
{// ....
};

五、設(shè)計(jì)一個(gè)類,只能創(chuàng)建一個(gè)對(duì)象(單例模式)

設(shè)計(jì)模式
設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。

為什么會(huì)產(chǎn)生設(shè)計(jì)模式這樣的東西呢?就像人類歷史發(fā)展會(huì)產(chǎn)生兵法。最開始部落之間打仗時(shí)都是人拼人的對(duì)砍。后來春秋戰(zhàn)國(guó)時(shí)期,七國(guó)之間經(jīng)常打仗,就發(fā)現(xiàn)打仗也是有套路的,后來孫子就總結(jié)出了《孫子兵法》。孫子兵法也是類似。
使用設(shè)計(jì)模式的目的:為了代碼可重用性、讓代碼更容易被他人理解、保證代碼可靠性。
設(shè)計(jì)模式使代碼編寫真正工程化;設(shè)計(jì)模式是軟件工程的基石脈絡(luò),如同大廈的結(jié)構(gòu)一樣。
單例模式:一個(gè)類只能創(chuàng)建一個(gè)對(duì)象,即單例模式,該模式可以保證系統(tǒng)中該類只有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn),該實(shí)例被所有程序模塊共享。比如在某個(gè)服務(wù)器程序中,該服務(wù)器的配置信息存放在一個(gè)文件中,這些配置數(shù)據(jù)由一個(gè)單例對(duì)象統(tǒng)一讀取,然后服務(wù)進(jìn)程中的其他對(duì)象再通過這個(gè)單例對(duì)象獲取這些配置信息,這種方式簡(jiǎn)化了在復(fù)雜環(huán)境下的配置管理。

對(duì)于單例模式我們首先需要解決一個(gè)問題:如果保證全局(一個(gè)進(jìn)程中)只有一個(gè)唯一實(shí)例對(duì)象

經(jīng)過上面的學(xué)習(xí)我們就可以知道,要想保證全局只有一個(gè)唯一實(shí)例對(duì)象我們需要做以下兩步操作

  • 構(gòu)造函數(shù)私有定義拷貝構(gòu)造和賦值防拷貝禁掉
  • 提供一個(gè)GetInstance獲取單例對(duì)象

單例模式有兩種實(shí)現(xiàn)模式:餓漢模式與懶漢模式

餓漢模式:就是說不管你將來用不用,程序啟動(dòng)時(shí)就創(chuàng)建一個(gè)唯一的實(shí)例對(duì)象。

下面來看餓漢模式的代碼:

主要有以下三個(gè)關(guān)鍵步驟

1、構(gòu)造函數(shù)私有? ?2、提供獲取單例對(duì)象的接口函數(shù)? ?3、防拷貝

經(jīng)過上面的學(xué)習(xí)我們就可以知道,為了防止被創(chuàng)建多個(gè)對(duì)象,所以我們要1、3這倆步,構(gòu)造函數(shù)私有定義。拷貝構(gòu)造和賦值防拷貝禁掉。

然后我們創(chuàng)建單例對(duì)象,?還要給它提供獲取單例對(duì)象的接口函數(shù)。

// 餓漢模式:一開始(main函數(shù)之前)就創(chuàng)建單例對(duì)象
// 提供一個(gè)靜態(tài)指向單例對(duì)象的成員指針,初始化時(shí)new一個(gè)對(duì)象給它
// 1、如果單例對(duì)象初始化內(nèi)容很多,影響啟動(dòng)速度
// 2、如果兩個(gè)單例類,互相有依賴關(guān)系。 
// 假設(shè)有A B兩個(gè)單例類,要求A先創(chuàng)建,B再創(chuàng)建,B的初始化創(chuàng)建依賴A
namespace hungry
{class Singleton{public:// 2、提供獲取單例對(duì)象的接口函數(shù)static Singleton& GetInstance(){return _sinst;}void func();void Add(const pair<string, string>& kv){_dict[kv.first] = kv.second;}void Print(){for (auto& e : _dict){cout << e.first << ":" << e.second << endl;}cout << endl;}private:// 1、構(gòu)造函數(shù)私有Singleton(){// ...}// 3、防拷貝Singleton(const Singleton& s) = delete;Singleton& operator=(const Singleton& s) = delete;map<string, string> _dict;// ...static Singleton _sinst;};Singleton Singleton::_sinst;void Singleton::func(){// _dict["xxx"] = "1111";}
}int main()
{//Singleton s1;//Singleton s2;cout << &hungry::Singleton::GetInstance() << endl;cout << &hungry::Singleton::GetInstance() << endl;cout << &hungry::Singleton::GetInstance() << endl;//Singleton copy(Singleton::GetInstance());hungry::Singleton::GetInstance().Add({ "xxx", "111" });hungry::Singleton::GetInstance().Add({ "yyy", "222" });hungry::Singleton::GetInstance().Add({ "zzz", "333" });hungry::Singleton::GetInstance().Add({ "abc", "333" });hungry::Singleton::GetInstance().Print();return 0;
}

運(yùn)行結(jié)果:

可以看到單例模式只能創(chuàng)建了一個(gè)對(duì)象

把其他的創(chuàng)建屏蔽掉再看運(yùn)行結(jié)果:

可以看到GetInstance()之后地址都是相同的,說明只創(chuàng)建了一個(gè)對(duì)象。并且能實(shí)現(xiàn)里面簡(jiǎn)單的功能

餓漢模式適用場(chǎng)景:

  • 如果這個(gè)單例對(duì)象在多線程高并發(fā)環(huán)境下頻繁使用,性能要求較高,那么顯然使用餓漢模式來避免資源競(jìng)爭(zhēng),提高響應(yīng)速度更好。

餓漢模式不適用場(chǎng)景:

  • 如果單例類構(gòu)造函數(shù)中,要做很多配置初始化工作,導(dǎo)致程序啟動(dòng)非常慢
  • 如果兩個(gè)單例類,互相有依賴關(guān)系。?假設(shè)有A B兩個(gè)單例類,要求A先創(chuàng)建,B再創(chuàng)建,B的初始化創(chuàng)建依賴A。我們?nèi)绾伪WC先創(chuàng)建A再創(chuàng)建B呢?

這個(gè)時(shí)候我們使用餓漢就不合適了,這時(shí)我們應(yīng)該使用下面的懶漢模式。

懶漢模式

如果單例對(duì)象構(gòu)造十分耗時(shí)或者占用很多資源,比如加載插件啊, 初始化網(wǎng)絡(luò)連接啊,讀取文件啊等等,而有可能該對(duì)象程序運(yùn)行時(shí)不會(huì)用到,那么也要在程序一開始就進(jìn)行初始化,就會(huì)導(dǎo)致程序啟動(dòng)時(shí)非常的緩慢。 所以這種情況使用懶漢模式(延遲加載)更好。

下面來看這段懶漢的代碼


namespace lazy
{//懶漢模式class Singleton{public:static Singleton* GetInstance(){if (_psinst == nullptr){_psinst = new Singleton;}return _psinst;}void Print(){cout << "Print()" << _a << endl;}private:Singleton():_a(0){}//C++98 防拷貝//Singleton(const Singleton&);//Singleton& operator=(const Singleton&);//C++11 防拷貝Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;int _a;static Singleton* _psinst;};Singleton* Singleton::_psinst = nullptr;}

但是這么寫是會(huì)存在一些問題的。

在多線程場(chǎng)景下會(huì)存在線程安全的問題,因?yàn)槲覀?strong>的懶漢式要用的時(shí)候才會(huì)去調(diào)用GetInstance函數(shù)再去創(chuàng)建那個(gè)唯一的對(duì)象。

假如說現(xiàn)在有兩個(gè)線程,分別是線程A與線程B,然后我線程A與線程B都調(diào)用了GetInstance函數(shù)線程A與線程B都進(jìn)入了if條件判斷里面,此時(shí)我們線程A如果先執(zhí)行實(shí)例化對(duì)象的代碼,然后返回。因?yàn)槲覀兊?strong>線程B不知道線程A已經(jīng)實(shí)例化了唯一對(duì)象,此時(shí)線程B再去調(diào)用實(shí)例化對(duì)象的代碼,就會(huì)導(dǎo)致前面的唯一對(duì)象的地址被覆蓋掉線程A的數(shù)據(jù)會(huì)丟失,并且會(huì)有內(nèi)存泄漏的風(fēng)險(xiǎn),更嚴(yán)重的是此時(shí)已經(jīng)產(chǎn)生了兩個(gè)實(shí)例對(duì)象,違反了單例模式的設(shè)計(jì)思想。

那我們應(yīng)如何解決上面的問題呢?我們需要進(jìn)行雙檢查加鎖。

//懶漢模式
#include <mutex> 
namespace lazy
{class Singleton{public:static Singleton* GetInstance(){// 保護(hù)第一次需要加鎖,后面都不需要加鎖的場(chǎng)景,可以使用雙檢查加鎖// 特點(diǎn):第一次加鎖,后面不加鎖,保護(hù)線程安全,同時(shí)提高了效率if (_pinst == nullptr){_mtx.lock();if (_pinst == nullptr){_pinst = new Singleton;}_mtx.unlock();}return _pinst;}static void DelInstance(){_mtx.lock();if (_pinst){delete _pinst;_pinst = nullptr;}_mtx.unlock();}void Print(){cout << "Print()" << _a << endl;}private:Singleton():_a(0){// 假設(shè)單例類構(gòu)造函數(shù)中,要做很多配置初始化}~Singleton(){// 程序結(jié)束時(shí),需要處理一下,持久化保存一些數(shù)據(jù)}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;// 實(shí)現(xiàn)一個(gè)內(nèi)嵌垃圾回收類    class CGarbo {public:~CGarbo(){if (_pinst){delete _pinst;_pinst = nullptr;}}};int _a;static Singleton* _pinst;static std::mutex _mtx;static CGarbo _gc;};Singleton* Singleton::_pinst = nullptr;std::mutex Singleton::_mtx;Singleton::CGarbo Singleton::_gc;
}

為什么是雙檢查加鎖?

我們需要知道我們想加鎖的地方只是第一次 _pinst為空的時(shí)候,我們想實(shí)例化一個(gè)唯一對(duì)象時(shí)才需要加鎖,但是如果到了后面我們已經(jīng)實(shí)例化出了對(duì)象,但是我們照樣加鎖了之后再去判斷 _pinst是否為空,然后在多線程場(chǎng)景下頻繁的加鎖解鎖會(huì)導(dǎo)致效率降低,并且也不推薦這樣做。

而我們的雙檢查加鎖里面的第二個(gè)if檢查就是我先進(jìn)行加鎖,然后進(jìn)行判斷第一次_pinst是否為空然后實(shí)例化一個(gè)唯一對(duì)象等到下一次某個(gè)線程再調(diào)用GetInstance的時(shí)候,我們的第一個(gè)if檢查發(fā)現(xiàn)pinst不為空,就不會(huì)進(jìn)入第一個(gè)if條件判斷的里面因此也就不存在多線程場(chǎng)景下頻繁加鎖解鎖,保護(hù)線程安全,同時(shí)提高了效率。
?

餓漢模式和懶漢模式的優(yōu)缺點(diǎn)對(duì)比如下:

餓漢模式:

  1. 優(yōu)點(diǎn):實(shí)例化對(duì)象在類加載時(shí)完成,因此無須考慮多線程訪問問題,可以確保實(shí)例的唯一性。
  2. 缺點(diǎn):
  • 餓漢式單例對(duì)象在類加載時(shí)就被創(chuàng)建,可能會(huì)造成系統(tǒng)資源的浪費(fèi),尤其是在對(duì)象占內(nèi)存較大或?qū)ο蟪跏蓟臅r(shí)較長(zhǎng)的情況下。
  • 如果有多個(gè)單例對(duì)象,他們之間有初始化依賴關(guān)系,餓漢模式也會(huì)有問題。(比如有A和B兩個(gè)單例類,要求A單例先初始化,B必須在A之后初始化。那么餓漢無法保證。這種場(chǎng)景下面用懶漢就可以,懶漢可以先調(diào)用A::GetInstance(),再調(diào)用B::GetInstance().)

懶漢模式:

  1. 優(yōu)點(diǎn):實(shí)現(xiàn)了延遲加載,只有在第一次使用時(shí)才創(chuàng)建實(shí)例,節(jié)省了系統(tǒng)資源。(解決餓漢的缺點(diǎn)。因?yàn)樗堑谝淮握{(diào)用GetInstance時(shí)創(chuàng)建初始化單例對(duì)象)
  2. 缺點(diǎn):必須考慮與處理多個(gè)線程同時(shí)訪問的問題,需要進(jìn)行雙重檢查鎖定等機(jī)制及進(jìn)行控制。
http://aloenet.com.cn/news/33987.html

相關(guān)文章:

  • 一般網(wǎng)站服務(wù)器配置高端網(wǎng)站建設(shè)企業(yè)
  • 網(wǎng)站建設(shè)全攻略百度谷歌seo優(yōu)化
  • 模塊網(wǎng)站開發(fā)合同注冊(cè)域名費(fèi)用一般多少錢
  • 做網(wǎng)站一定要用cms嗎簡(jiǎn)述seo的基本步驟
  • 大連企業(yè)做網(wǎng)站seo按天計(jì)費(fèi)系統(tǒng)
  • 網(wǎng)站做微信支付對(duì)接市場(chǎng)營(yíng)銷方案怎么做
  • 做logo好的網(wǎng)站北京網(wǎng)站快速排名優(yōu)化
  • 代充網(wǎng)站怎么做網(wǎng)站建設(shè)制作費(fèi)用
  • 上海百度嘉定公司網(wǎng)頁(yè)設(shè)計(jì)提升seo排名
  • 安徽城鄉(xiāng)建設(shè)廳網(wǎng)站一鍵關(guān)鍵詞優(yōu)化
  • 做醫(yī)療網(wǎng)站聚名網(wǎng)域名注冊(cè)
  • 網(wǎng)站服務(wù)器 優(yōu)幫云外貿(mào)推廣代理
  • 鄰水網(wǎng)站建設(shè)友情鏈接檢測(cè)659292
  • 鎮(zhèn)江手機(jī)網(wǎng)站建設(shè)seo基礎(chǔ)篇
  • 海南最新情況最新消息今天網(wǎng)站seo入門基礎(chǔ)教程
  • 排名優(yōu)化網(wǎng)站網(wǎng)絡(luò)推廣哪家好
  • 事業(yè)單位網(wǎng)站開發(fā)工作規(guī)程網(wǎng)站優(yōu)化seo方案
  • 什么是項(xiàng)目管理小小課堂seo自學(xué)網(wǎng)
  • 婚紗攝影網(wǎng)站建設(shè)新聞稿發(fā)布
  • 珠寶網(wǎng)站設(shè)計(jì)今日熱點(diǎn)新聞素材
  • sae安裝WordPress4.4合肥品牌seo
  • 蔬菜派送網(wǎng)站怎么做輔導(dǎo)班培訓(xùn)機(jī)構(gòu)
  • 內(nèi)蒙古地區(qū)做推廣網(wǎng)站搜索引擎推廣試題
  • 哈爾濱網(wǎng)站建設(shè)技術(shù)托管國(guó)家再就業(yè)免費(fèi)培訓(xùn)網(wǎng)
  • 如何申請(qǐng)域名建立網(wǎng)站資源最全的網(wǎng)盤搜索引擎
  • 網(wǎng)站內(nèi)容營(yíng)銷武漢seo推廣優(yōu)化公司
  • 做網(wǎng)站個(gè)人怎么簽合同長(zhǎng)沙全網(wǎng)覆蓋的網(wǎng)絡(luò)推廣
  • 網(wǎng)站設(shè)計(jì)效果專業(yè)樂云seoseo優(yōu)化專員招聘
  • b2b電商網(wǎng)站建設(shè)總推薦榜總點(diǎn)擊榜總排行榜
  • 手機(jī)商城網(wǎng)站如何開發(fā)一個(gè)網(wǎng)站