特點
保證一個類僅有一個實例,並提供一個訪問它的全局訪問點,該實例被所有程序模塊共享
懶漢式
特點
第一次調用才初始化 避免浪費內存
必須加鎖才能保證單例 但是加鎖影響效率
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;
};
線程安全/內存泄漏問題
多線程下的該類可能會引發競態條件
第一個線程正在判斷全局指針是否爲空,此時類尚未實例化,所以全局指針爲空,其他線程到此 判斷後發現指針爲空,此時第一個線程才實例化了第一個類,故此,可能違背單例模式的原則,一個類實例化了多個對象出來。
解決方法
使用加鎖和智能指針的改良方案
在這裏插入代碼片