亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2020-06-17 16:36:20 來源:網絡 閱讀:219 作者:給我個bit位 欄目:編程語言

    有時候實現了一個類,但只需要創建出一個實例化的對象就能完成需求,如果有太多的對象不僅浪費內存空間也會使得代碼數據不那么好維護,因此會需要設計出一個只能生成一個實例的類;

    首先,要使得這個類只能實例化出一個對象,那么它的構造函數肯定不能夠被外部隨意調用,因此應該將類的構造函數的訪問限定符設定為私有的,但是這樣的話,如何獲得唯一一個的實例化對象呢?可以設計一個成員函數,這個成員函數只能分配出唯一一個該類對象的內存空間,并且返回指向這塊空間的指針給申請的對象,因此,可以將類設計為如下:

#include <iostream>
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;

    上面的栗子中將構造函數、拷貝構造和賦值運算符的重載函數的訪問限定符置為私有的,外界不能通過這些函數實例化出對象;然后設計了一個靜態成員函數,這里值得一提的是,靜態的成員函數沒有隱含的this指針,因此外界可以通過類名加域的訪問符號::來調用靜態的成員函數

    類的成員變量只定義了一個指向類對象的一個_instance指針,靜態的成員函數可以在類外部初始化,先將其初始化為NULL,當第一次調用這個GetInstance函數的時候,_instance為NULL,因此為其分配一個類對象的空間并將其返回;但是當第二次調用這個函數的時候,_instance已經有了值并不會再分配空間而是返回已經存在的實例化出的對象,因此無論怎么調用GetInstance函數都只會返回同一塊地址空;

    但是上面的函數在單線程環境下運行是沒有問題的,當有多個線程并發訪問這個函數的時候,如果兩個或多個線程同時拿到了初始化為NULL的_instance的值要進行判斷的時候,有可能都會判斷成功,也就是會new出來兩塊不同的地址空間,這樣就不符合設計的初衷了,因此在多線程運行環境下,GetInstance函數中的代碼就會成為臨界區,也就是要有互斥的關系,可以為其加上mutex互斥鎖:

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

    可是上面的代碼還是存在一些效率的問題,如果一個線程最開始獲得了鎖并且成功new出了空間,那么之后的線程每一次進到函數GetInstance里面都要爭奪一下鎖資源并且再依次判斷,所以,可以在加鎖之前就先進行一次判斷,如果_instance不為空,后面就沒有必要競爭鎖資源再進行判斷了,所以代碼可以優化為如下:

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


    其實除了上面所給出的解法,還有另外一種簡單粗暴的設計方式,那就是直接在給靜態成員變量_instance初始化的時候就初始化為new出來的一個類的實例化對象,之后每一次調用GetInstance函數獲取_instance的值的時候就直接返回:

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();


    上面一次性就將對象空間給開辟出來每次不用判斷就直接返回,這種方式被稱為餓漢式,相當于用空間換時間;而前面一種在需要的時候去判斷然后開辟空間,這種方式被叫做懶漢式,就相當于用時間來換空間了,各有利弊。


《完》

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

和田县| 成武县| 于都县| 德兴市| 昆明市| 横山县| 弥勒县| 荔波县| 贞丰县| 新营市| 昆明市| 教育| 罗定市| 高碑店市| 舞阳县| 双柏县| 宁夏| 皮山县| 江山市| 天全县| 呼伦贝尔市| 英山县| 广南县| 渭南市| 中阳县| 搜索| 昔阳县| 武邑县| 枣强县| 托里县| 宁晋县| 六枝特区| 慈利县| 河南省| 赞皇县| 隆德县| 体育| 麻城市| 图木舒克市| 庆城县| 平潭县|