设计模式:单例模式
懒汉式单例模式
#include <iostream>
/*
单例模式:一个类不管创建多少个对象,永远只能得到该类型一个对象的实例
常用到,比如日志模块、数据库模块
单例模式类型:
饿汉式单例模式:还没有获取实例对象,实例对象就已经产生了(导致程序启动时就需要实例化调用构造函数,如果构造函数需要做大量消耗资源会导致程序启动耗时)
懒汉式单例模式:唯一的实例对象,直到第一次获取它的时候,才产生
*/
//饿汉式单例模式 一定是线程安全的
class Singleton
{
public:
static Singleton* getInstance() //#3 获取类的唯一实例对象的接口方法(必须时静态,静态时为方法便类调用,因为外部不能创建出对象,不能通过对象调用)
{
return &instance;
}
private:
Singleton()//#1 构造函数私有化
{
}
Singleton(const Singleton&) = delete;//禁用默认拷贝构造函数
Singleton & operator=(const Singleton&) = delete;//禁用默认赋值重载函数
static Singleton instance;//#2 定义一个唯一的类的实例对象
};
Singleton Singleton::instance;//静态程序变量需要在类外初始化
int main()
{
Singleton* p1 = Singleton::getInstance();
Singleton* p2 = Singleton::getInstance();
Singleton* p3= Singleton::getInstance();
std::cout << " p1 memroy addr :" << p1 << std::endl;
std::cout << " p2 memory addr: " << p2 << std::endl;
std::cout << " p3 memory addr: " << p3 << std::endl;
//Singleton p4(*p3);//会拷贝构造一个新的实例,所以需要禁用拷贝构造
//std::cout << " p4 memory addr: " << &p4 << std::endl;
//Singleton p5=*p3;//默认赋值重载函数会产生新的实例,所以需要禁用默认赋值重载
//std::cout << " p5 memory addr: " << &p5 << std::endl;
}
输出信息
p1 memroy addr :00007FF75578F1B0
p2 memory addr: 00007FF75578F1B0
p3 memory addr: 00007FF75578F1B0
饿汉单例模式
方案一:锁+双重判断
#include <iostream>
#include <mutex>
/*
单例模式:一个类不管创建多少个对象,永远只能得到该类型一个对象的实例
常用到,比如日志模块、数据库模块
单例模式类型:
饿汉式单例模式:还没有获取实例对象,实例对象就已经产生了(导致程序启动时就需要实例化调用构造函数,如果构造函数需要做大量消耗资源会导致程序启动耗时)
懒汉式单例模式:唯一的实例对象,直到第一次获取它的时候,才产生
*/
std::mutex mtx;
//懒汉式单例模式
class Singleton
{
public:
//是不是可重入函数呢?
//是可以重入的,比如如果线程1 new Singleton() 开辟内存且构造对象,但未给instance赋值,但是时间片给线程2,线程2因为instance==nullptr 这时重入也会new Singleton()导致重新构造对象
//解决办法:锁+双重判断
static Singleton* getInstance() //#3 获取类的唯一实例对象的接口方法
{
if (instance == nullptr)//第一重判断
{
std::lock_guard<std::mutex> guard(mtx);
if (instance == nullptr)//第二重判断
{
/*
开辟内存
构造对象
给instance赋值
*/
instance = new Singleton();
}
}
return instance;
}
private:
Singleton()//#1 构造函数私有化
{
}
Singleton(const Singleton&) = delete;//禁用默认拷贝构造函数
Singleton& operator=(const Singleton&) = delete;//禁用默认赋值重载函数
//加入volatile的好处:修饰指针,不是修饰指针的指向
//volatile可以让线程A的修改,让线程B能立即看见。线程不会对instance进行缓存,写入和读取都是内存中的值
static Singleton * volatile instance;//#2 定义一个唯一的类的实例对象
};
Singleton* volatile Singleton::instance = nullptr;//静态程序变量需要在类外初始化
int main()
{
Singleton* p1 = Singleton::getInstance();
Singleton* p2 = Singleton::getInstance();
Singleton* p3 = Singleton::getInstance();
std::cout << " p1 memroy addr :" << p1 << std::endl;
std::cout << " p2 memory addr: " << p2 << std::endl;
std::cout << " p3 memory addr: " << p3 << std::endl;
//Singleton p4(*p3);//会拷贝构造一个新的实例,所以需要禁用拷贝构造
//std::cout << " p4 memory addr: " << &p4 << std::endl;
//Singleton p5=*p3;//默认赋值重载函数会产生新的实例,所以需要禁用默认赋值重载
//std::cout << " p5 memory addr: " << &p5 << std::endl;
}
输出信息如下
p1 memroy addr :000001C9F9A5C2A0
p2 memory addr: 000001C9F9A5C2A0
p3 memory addr: 000001C9F9A5C2A0
方案二:简单方式实现
#include <iostream>
#include <mutex>
/*
单例模式:一个类不管创建多少个对象,永远只能得到该类型一个对象的实例
常用到,比如日志模块、数据库模块
单例模式类型:
饿汉式单例模式:还没有获取实例对象,实例对象就已经产生了(导致程序启动时就需要实例化调用构造函数,如果构造函数需要做大量消耗资源会导致程序启动耗时)
懒汉式单例模式:唯一的实例对象,直到第一次获取它的时候,才产生
*/
std::mutex mtx;
//懒汉式单例模式
class Singleton
{
public:
static Singleton* getInstance() //#3 获取类的唯一实例对象的接口方法
{
//TODO:再linux系统上进行分析,查看汇编指令 g++ -o run 单例模式.cpp -g gdb run
//函数静态局部变量的初始化,在汇编指令上已经自动添加线程互斥指令了
static Singleton instance;//#2 定义一个唯一的类的实例对象
return &instance;
}
private:
Singleton()//#1 构造函数私有化
{
}
Singleton(const Singleton&) = delete;//禁用默认拷贝构造函数
Singleton& operator=(const Singleton&) = delete;//禁用默认赋值重载函数
};
int main()
{
Singleton* p1 = Singleton::getInstance();
Singleton* p2 = Singleton::getInstance();
Singleton* p3 = Singleton::getInstance();
std::cout << " p1 memroy addr :" << p1 << std::endl;
std::cout << " p2 memory addr: " << p2 << std::endl;
std::cout << " p3 memory addr: " << p3 << std::endl;
//Singleton p4(*p3);//会拷贝构造一个新的实例,所以需要禁用拷贝构造
//std::cout << " p4 memory addr: " << &p4 << std::endl;
//Singleton p5=*p3;//默认赋值重载函数会产生新的实例,所以需要禁用默认赋值重载
//std::cout << " p5 memory addr: " << &p5 << std::endl;
}
输出如下:
p1 memroy addr :00007FF7D559F230
p2 memory addr: 00007FF7D559F230
p3 memory addr: 00007FF7D559F230
浙公网安备 33010602011771号