欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報(bào)邀請(qǐng)碼778899分享:C++設(shè)計(jì)模式 —— 單例模式

柚子快報(bào)邀請(qǐng)碼778899分享:C++設(shè)計(jì)模式 —— 單例模式

http://yzkb.51969.com/

設(shè)計(jì)模式 —— 單例模式

一個(gè)問題C++11后代寫法單例模式的兩種模式餓漢模式懶漢模式

在了解C++面向?qū)ο蟮娜筇匦裕悍庋b,繼承,多態(tài)之后。我們創(chuàng)建類的時(shí)候就有了比較大的空間。但是,我們平時(shí)在創(chuàng)建類的時(shí)候,不是簡(jiǎn)單寫個(gè)class和繼承關(guān)系就完事了的。我們寫的類要在一些場(chǎng)景下滿足一些特殊的要求。

一個(gè)問題

現(xiàn)在有一個(gè)具體的要求,創(chuàng)建一個(gè)類,保證處處只有一個(gè)實(shí)體,這個(gè)要求在平常的工作中是很常見的, 配置文件管理,日志系統(tǒng),數(shù)據(jù)庫連接池, 線程池等。

如何實(shí)現(xiàn)呢?保證只有一個(gè)實(shí)體,可以考慮靜態(tài)成員變量,我們之前在C++繼承中說過,無論繼承關(guān)系有多少層,只要為靜態(tài)成員,全局就只有一份。所以我們可以先從這個(gè)方向入手。

//單例模式

class SingleClass

{

public:

static SingleClass* GetInstance()

{

if (instance == nullptr)

{

instance = new SingleClass();

}

return instance;

}

static SingleClass* instance;

};

//靜態(tài)成員在外部初始化

SingleClass* SingleClass::instance = nullptr;

int main()

{

SingleClass* s1 = SingleClass::GetInstance();

SingleClass* s2 = SingleClass::GetInstance();

if (s1 == s2)

{

std::cout << "s1和s2為同一實(shí)體" << std::endl;

}

else

{

std::cout << "s1和s2不為同一實(shí)體" << std::endl;

}

}

這樣看上去問題解決了,但是: 我們可以在類外創(chuàng)建對(duì)象,這不符合我們的要求,究其原因,我們把構(gòu)造函數(shù)設(shè)為了公有解決這個(gè)問題將它聲明為私有就可以了。

//單例模式

class SingleClass

{

public:

static SingleClass* GetInstance()

{

if (instance == nullptr)

{

instance = new SingleClass();

}

return instance;

}

private:

SingleClass(){} //構(gòu)造函數(shù)為私有

static SingleClass* instance;

};

這樣就可以了,但是別忘了我們還有拷貝構(gòu)造和賦值拷貝,這兩個(gè)也可以構(gòu)造出新對(duì)象,所以為了保險(xiǎn)可以直接把他倆禁了:

//單例模式

class SingleClass

{

public:

static SingleClass* GetInstance()

{

if (instance == nullptr)

{

instance = new SingleClass();

}

return instance;

}

private:

SingleClass(){} //構(gòu)造函數(shù)為私有

SingleClass(const SingleClass&) = delete; // 禁止拷貝構(gòu)造

SingleClass& operator=(const SingleClass&) = delete; // 禁止賦值操作

static SingleClass* instance;

};

//靜態(tài)成員在外部初始化

SingleClass* SingleClass::instance = nullptr;

這就是單例模式的雛形了。

單例模式(Singleton Pattern) 實(shí)現(xiàn)一個(gè)類保證處處只有一個(gè)實(shí)例。單例模式的核心思想是:

私有化構(gòu)造函數(shù):禁止外部直接創(chuàng)建對(duì)象。

靜態(tài)方法獲取實(shí)例:通過靜態(tài)成員函數(shù)控制唯一實(shí)例的創(chuàng)建和訪問。

禁止拷貝和賦值:防止通過拷貝構(gòu)造函數(shù)或賦值操作生成新實(shí)例。

上面的代碼還不能保證在多線程條件下是安全的的:

//單例模式

class SingleClass

{

public:

static SingleClass* GetInstance()

{

if (instance == nullptr)

{

instance = new SingleClass();

}

return instance;

}

void PrintAddress()

{

std::cout << "地址為:" << this << std::endl;

}

private:

SingleClass(){} //構(gòu)造函數(shù)為私有

SingleClass(const SingleClass&) = delete; // 禁止拷貝構(gòu)造

SingleClass& operator=(const SingleClass&) = delete; // 禁止賦值操作

static SingleClass* instance;

//static std::mutex mtx;

};

//靜態(tài)成員在外部初始化

SingleClass* SingleClass::instance = nullptr;

//std::mutex SingleClass::mtx;

// 全局互斥鎖,用于保護(hù)輸出

std::mutex coutMtx;

// 線程函數(shù)

void threadFunc()

{

SingleClass* instance = SingleClass::GetInstance();

std::lock_guard lock(coutMtx); // 加鎖保護(hù)輸出

instance->PrintAddress();

}

int main()

{

const int threadNumber = 100;

std::vector threadVT;

//創(chuàng)建多個(gè)線程

for (int i = 0; i < threadNumber; i++)

{

threadVT.emplace_back(threadFunc);

}

for (auto& t : threadVT)

{

t.join();

}

}

大家可以試一下,可能會(huì)有不同的地址。為了保證線程安全,我們還得加鎖:

//單例模式

class SingleClass

{

public:

static SingleClass* GetInstance()

{

if (instance == nullptr)

{

std::lock_guard lock(mtx); // 加鎖

instance = new SingleClass();

}

return instance;

}

private:

SingleClass(){} //構(gòu)造函數(shù)為私有

SingleClass(const SingleClass&) = delete; // 禁止拷貝構(gòu)造

SingleClass& operator=(const SingleClass&) = delete; // 禁止賦值操作

static SingleClass* instance;

static std::mutex mtx;

};

//靜態(tài)成員在外部初始化

SingleClass* SingleClass::instance = nullptr;

std::mutex SingleClass::mtx;

C++11后代寫法

在 C++11 中,局部靜態(tài)變量的初始化是線程安全的,因此可以簡(jiǎn)化代碼

class SingleClass

{

public:

static SingleClass& GetInstance()

{

static SingleClass instance;

return instance;

}

private:

SingleClass() {};

SingleClass(const SingleClass&) = delete; // 禁止拷貝構(gòu)造

SingleClass& operator=(const SingleClass&) = delete; // 禁止賦值操作

};

int main()

{

SingleClass& s1 = SingleClass::GetInstance();

SingleClass& s2 = SingleClass::GetInstance();

if (&s1 == &s2)

{

std::cout << "s1和s2同一對(duì)象" << std::endl;

}

else

{

std::cout << "s1和s2不為同一對(duì)象" << std::endl;

}

}

單例模式的兩種模式

餓漢模式

餓漢模式講究的是對(duì)象已經(jīng)創(chuàng)建好,要用的時(shí)候直接拿就行

class SingleClass

{

public:

static SingleClass* GetInstance()

{

return instance;

}

private:

SingleClass() {}

SingleClass(const SingleClass&) = delete; // 禁止拷貝構(gòu)造

SingleClass& operator=(const SingleClass&) = delete; // 禁止賦值操作

static SingleClass* instance;

};

SingleClass* SingleClass::instance = new SingleClass();

懶漢模式

懶漢模式講究的是對(duì)象要用時(shí)才創(chuàng)建:

class SingleClass

{

public:

static SingleClass* GetInstance()

{

if (instance == nullptr)

{

instance = new SingleClass();

return instance;

}

}

private:

SingleClass() {}

SingleClass(const SingleClass&) = delete; // 禁止拷貝構(gòu)造

SingleClass& operator=(const SingleClass&) = delete; // 禁止賦值操作

static SingleClass* instance;

};

SingleClass* SingleClass::instance = nullptr;

這個(gè)和我們最開始寫的代碼差不多,要改進(jìn)的話還要保證線程安全。

我們可以將這種思想放到我們實(shí)際的代碼中,比如我們?nèi)罩鞠到y(tǒng)的開發(fā):

class LoggerManager

{

public:

static LoggerManager &getInstance()

{

// c++11之后,針對(duì)靜態(tài)局部變量,編譯器在編譯的層面實(shí)現(xiàn)了線程安全

// 當(dāng)靜態(tài)局部變量在沒有構(gòu)造完成之前,其他的線程進(jìn)入就會(huì)阻塞

static LoggerManager eton;

return eton;

}

void addLogger(logs::logger::ptr &logger)

{

if (hasLogger(logger->name()))

return;

std::unique_lock lock(_mutex);

_loggers.insert(std::make_pair(logger->name(), logger));

}

bool hasLogger(const std::string &name)

{

std::unique_lock lock(_mutex);

auto it = _loggers.find(name);

if (it == _loggers.end())

{

return false;

}

return true;

}

logs::logger::ptr getLogger(const std::string &name)

{

std::unique_lock lock(_mutex);

auto it = _loggers.find(name);

if (it == _loggers.end())

{

return logger::ptr();

}

return it->second;

}

logs::logger::ptr rootLogger()

{

return _root_logger;

}

private:

LoggerManager()

{

std::unique_ptr builder(new logs::LocalloggerBuild());

builder->buildLoggerName("root");

_root_logger = builder->build();

_loggers.insert(std::make_pair("root", _root_logger));

}

private:

std::mutex _mutex;

logs::logger::ptr _root_logger; // 默認(rèn)日志器

std::unordered_map _loggers;

};

柚子快報(bào)邀請(qǐng)碼778899分享:C++設(shè)計(jì)模式 —— 單例模式

http://yzkb.51969.com/

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/2027250922.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄