單例模式 C++

特點

保證一個類僅有一個實例,並提供一個訪問它的全局訪問點,該實例被所有程序模塊共享

懶漢式

特點

第一次調用才初始化 避免浪費內存
必須加鎖才能保證單例 但是加鎖影響效率

demo

//
// Created by xatusec on 2019/12/3.
//

//.h
#ifndef SINGLETON_SINGLETON_H
#define SINGLETON_SINGLETON_H

#include <iostream>

class Singleton
{

public:
    static Singleton * GetInstance();
private:
    Singleton();
    static Singleton *m_pInstance;
};

#endif //SINGLETON_SINGLETON_H
//.cpp
#include "Singleton.h"



Singleton *Singleton::GetInstance()
{
    if(m_pInstance == nullptr)
    {
        m_pInstance = new Singleton();
    }
    return m_pInstance;
}

Singleton::Singleton()
{
        std::cout << "Singleton()" << std::endl;
}


Singleton *Singleton::m_pInstance = nullptr;
//.main
#include "Singleton.h"
#include<iostream>
using namespace std;

int main()
{

    Singleton *p1 = Singleton::GetInstance();
    Singleton *p2 = Singleton::GetInstance();

    cout << "p1 address:"<< p1 <<endl;
    cout << "p2 address:"<< p2 << endl;
}

結果

在這裏插入圖片描述
兩者地址相同 保證指向的是在內存中的同一個空間 實現了一個類只初始化一個實例

不重寫拷貝構造/運算符重載存在問題

沒有完全保證一個類只有一個實例(沒有重寫/禁用拷貝構造和運算符重載)改寫main中的代碼 結果如下

更改main.cpp爲

#include "Singleton.h"

#include<iostream>
using namespace std;

int main()
{

	Singleton* p1 = Singleton::GetInstance();
	Singleton* p2 = Singleton::GetInstance();

	cout << "p1 address:" << p1 << endl;
	cout << "p2 address:" << p2 << endl;

	Singleton p3(*p1);
	Singleton p4 = *p1;

	cout << "p3 address:" << &p3 << endl;
	cout << "p4 address:" << &p4 << endl;
}

結果爲
在這裏插入圖片描述
很明顯 一個類生成了三個實例,不符合單例模式的要求

重寫/刪除拷貝構造個運算符重載

重寫Singleton中拷貝構造函數和運算符重載

#include <iostream>

class Singleton
{
public:
	static Singleton* GetInstance();

private:
	Singleton(const Singleton& Single);
	void operator= (const Singleton& Single);
	Singleton();
	static Singleton* m_pInstance;
};

在這裏插入圖片描述
保險起見 刪除上述函數

#include <iostream>

class Singleton
{
public:
	static Singleton* GetInstance();

private:
	Singleton(const Singleton& Single) = delete;
	void operator= (const Singleton& Single) = delete;
	Singleton();
	static Singleton* m_pInstance;
};

線程安全/內存泄漏問題

多線程下的該類可能會引發競態條件
第一個線程正在判斷全局指針是否爲空,此時類尚未實例化,所以全局指針爲空,其他線程到此 判斷後發現指針爲空,此時第一個線程才實例化了第一個類,故此,可能違背單例模式的原則,一個類實例化了多個對象出來。

解決方法

使用加鎖和智能指針的改良方案

在這裏插入代碼片

餓漢式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章