真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C++中的單例模式——2

    有時(shí)候?qū)崿F(xiàn)了一個(gè)類,但只需要?jiǎng)?chuàng)建出一個(gè)實(shí)例化的對(duì)象就能完成需求,如果有太多的對(duì)象不僅浪費(fèi)內(nèi)存空間也會(huì)使得代碼數(shù)據(jù)不那么好維護(hù),因此會(huì)需要設(shè)計(jì)出一個(gè)只能生成一個(gè)實(shí)例的類;

在冠縣等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供做網(wǎng)站、成都網(wǎng)站設(shè)計(jì) 網(wǎng)站設(shè)計(jì)制作按需規(guī)劃網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),全網(wǎng)整合營(yíng)銷推廣,外貿(mào)營(yíng)銷網(wǎng)站建設(shè),冠縣網(wǎng)站建設(shè)費(fèi)用合理。

    首先,要使得這個(gè)類只能實(shí)例化出一個(gè)對(duì)象,那么它的構(gòu)造函數(shù)肯定不能夠被外部隨意調(diào)用,因此應(yīng)該將類的構(gòu)造函數(shù)的訪問(wèn)限定符設(shè)定為私有的,但是這樣的話,如何獲得唯一一個(gè)的實(shí)例化對(duì)象呢?可以設(shè)計(jì)一個(gè)成員函數(shù),這個(gè)成員函數(shù)只能分配出唯一一個(gè)該類對(duì)象的內(nèi)存空間,并且返回指向這塊空間的指針給申請(qǐng)的對(duì)象,因此,可以將類設(shè)計(jì)為如下:

#include 
using namespace std;

class Singleton
{
private:
    Singleton()
    {}  
    Singleton(Singleton& s); 
    Singleton& operator=(Singleton& s); 

public:
    static Singleton*& GetInstance()
    {   
        if(_instance == NULL)
        { 
            _instance = new Singleton();
        } 
        return _instance;
    }
    
    ~Singleton()
    {
        if(_instance != NULL)
            delete _instance;
    }

private:
    static Singleton *_instance;
};
Singleton* Singleton::_instance = NULL;

    上面的栗子中將構(gòu)造函數(shù)、拷貝構(gòu)造和賦值運(yùn)算符的重載函數(shù)的訪問(wèn)限定符置為私有的,外界不能通過(guò)這些函數(shù)實(shí)例化出對(duì)象;然后設(shè)計(jì)了一個(gè)靜態(tài)成員函數(shù),這里值得一提的是,靜態(tài)的成員函數(shù)沒(méi)有隱含的this指針,因此外界可以通過(guò)類名加域的訪問(wèn)符號(hào)::來(lái)調(diào)用靜態(tài)的成員函數(shù);

    類的成員變量只定義了一個(gè)指向類對(duì)象的一個(gè)_instance指針,靜態(tài)的成員函數(shù)可以在類外部初始化,先將其初始化為NULL,當(dāng)?shù)谝淮握{(diào)用這個(gè)GetInstance函數(shù)的時(shí)候,_instance為NULL,因此為其分配一個(gè)類對(duì)象的空間并將其返回;但是當(dāng)?shù)诙握{(diào)用這個(gè)函數(shù)的時(shí)候,_instance已經(jīng)有了值并不會(huì)再分配空間而是返回已經(jīng)存在的實(shí)例化出的對(duì)象,因此無(wú)論怎么調(diào)用GetInstance函數(shù)都只會(huì)返回同一塊地址空;

    但是上面的函數(shù)在單線程環(huán)境下運(yùn)行是沒(méi)有問(wèn)題的,當(dāng)有多個(gè)線程并發(fā)訪問(wèn)這個(gè)函數(shù)的時(shí)候,如果兩個(gè)或多個(gè)線程同時(shí)拿到了初始化為NULL的_instance的值要進(jìn)行判斷的時(shí)候,有可能都會(huì)判斷成功,也就是會(huì)new出來(lái)兩塊不同的地址空間,這樣就不符合設(shè)計(jì)的初衷了,因此在多線程運(yùn)行環(huán)境下,GetInstance函數(shù)中的代碼就會(huì)成為臨界區(qū),也就是要有互斥的關(guān)系,可以為其加上mutex互斥鎖:

static Singleton*& GetInstance()
{
    pthread_mutex_lock(&lock);
    if(_instance == NULL)
    {
        _instance = new Singleton();
    }
    pthread_mutex_unlock(&lock);
    return _instance;
}

    可是上面的代碼還是存在一些效率的問(wèn)題,如果一個(gè)線程最開(kāi)始獲得了鎖并且成功new出了空間,那么之后的線程每一次進(jìn)到函數(shù)GetInstance里面都要爭(zhēng)奪一下鎖資源并且再依次判斷,所以,可以在加鎖之前就先進(jìn)行一次判斷,如果_instance不為空,后面就沒(méi)有必要競(jìng)爭(zhēng)鎖資源再進(jìn)行判斷了,所以代碼可以優(yōu)化為如下:

static Singleton*& GetInstance()
{
    if(_instance == NULL)
    {
        pthread_mutex_lock(&lock);
        if(_instance == NULL)
        {
            _instance = new Singleton();
        }
        pthread_mutex_unlock(&lock);
    }
    return _instance;
}

    其實(shí)除了上面所給出的解法,還有另外一種簡(jiǎn)單粗暴的設(shè)計(jì)方式,那就是直接在給靜態(tài)成員變量_instance初始化的時(shí)候就初始化為new出來(lái)的一個(gè)類的實(shí)例化對(duì)象,之后每一次調(diào)用GetInstance函數(shù)獲取_instance的值的時(shí)候就直接返回:

class Singleton
{
private:
    Singleton()
    {}  
    Singleton(Singleton& s); 
    Singleton& operator=(Singleton& s); 

public:
    static Singleton*& GetInstance()
    {   
        return _instance;
    }   

private:
    static Singleton *_instance;
};
Singleton* Singleton::_instance = new Singleton();

    上面一次性就將對(duì)象空間給開(kāi)辟出來(lái)每次不用判斷就直接返回,這種方式被稱為餓漢式,相當(dāng)于用空間換時(shí)間;而前面一種在需要的時(shí)候去判斷然后開(kāi)辟空間,這種方式被叫做懶漢式,就相當(dāng)于用時(shí)間來(lái)?yè)Q空間了,各有利弊。

《完》


分享標(biāo)題:C++中的單例模式——2
URL地址:http://weahome.cn/article/igjohd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部