C++实现单例模式

单例模式是一种创建型模式,核心思想是保证一个类只有一个实例,并对外提供一个全局访问点来访问这个实例

单例模式分为两种:

  • 饿汉式:指的是在程序一加载就创建实例,因此称为饿汉式。这样的好处是没有多线程竞争,缺点是如果后面没有使用到这个单例,就浪费了。
  • 懒汉式:指的是到要用的时候才创建,因此称为懒汉式。这种方式可能会有多线程冲突,因此程序运行中,可能有多个线程都想创建单例,因此需要使用相应的机制避免冲突。程序需要的时候才进行实例化,提高了性能。

单例模式的优点:

  1. 全局控制:保证只有一个实例,就可以严格控制什么时候如何访问
  2. 节省资源:因为只有一个实例,不会创建多个实例,自然就更节省资源了

单例模式实现的几个要点:

  • 私有的构造函数:防止外部直接创建
  • 私有的静态实例变量:保存唯一实例
  • 公有的访问方法:对外的唯一方法来获取实例

下面是一个常见的懒汉式实现方式:

cpp 复制代码
// singleton.h

#pragma once
#include <mutex>
using namespace std;

class Singleton {
private:
	Singleton() = default;  // 私有构造,禁止外部构造
	~Singleton() = default; // 私有析构,禁止外部析构
	Singleton(const Singleton&) = delete; // 删除拷贝构造函数
	Singleton& operator=(const Singleton&) = delete; // 删除赋值函数
public:
	// 外部接口,获取单例实例对象
	static Singleton* getInstance(); 

	// 释放单例
	static void deleteInstance();

	void print();
private:
	static Singleton* instance; // 唯一的单例对象指针
	static mutex mtx;
};
cpp 复制代码
// singleton.cpp
#include <iostream>
#include "singleton.h"

Singleton* Singleton::instance = nullptr;
mutex Singleton::mtx;
Singleton* Singleton:: getInstance() {
	// 这两个if称为双重检测
	if (instance == nullptr) {
		unique_lock<mutex> lck(mtx);
		if (instance == nullptr) {
			instance = new Singleton();
			return instance;
		}
	}
	return instance;
}

void Singleton::deleteInstance() {
	unique_lock<mutex> lck(mtx);
	if (instance != nullptr) {
		delete instance;
		instance = nullptr;
	}
}

void Singleton::print() { std::cout << "实例地址:" << this << std::endl; }
cpp 复制代码
int main() {
	Singleton::getInstance(); // 获取单例
	Singleton::getInstance()->print();
	return 0;
}

为什么要使用双重检测(上面的两个if)

第一个if很好理解,当实例为空的时候才去创建。第二个if是为了保证只有一个线程拿到锁去创建实例。通俗的说,当进入第一个if后,这时候可能有多个线程来获取锁,如果不第二次判空,就可能创建出多个实例。

饿汉式实现:

cpp 复制代码
class Singleton {
private:
	Singleton() = default;  // 私有构造,禁止外部构造
	~Singleton() = default; // 私有析构,禁止外部析构
	Singleton(const Singleton&) = delete; // 删除拷贝构造函数
	Singleton& operator=(const Singleton&) = delete; // 删除赋值函数
public:
	// 外部接口,获取单例实例对象
	static Singleton* getInstance() {
		return instance;
	}
	void deleteInstance() {
		if (instance != nullptr) {
			delete instance;
			instance = nullptr;
		}
	}
	void print() { std::cout << "实例地址:" << this << std::endl; }
private:
	static Singleton* instance;
};
// 程序一启动就创建,没有多线程冲突
Singleton* Singleton::instance = new Singleton();

int main() {
	Singleton::getInstance();
	Singleton::getInstance()->print();
	return 0;
}

更多的单例模式实现方式可参考:
https://blog.csdn.net/unonoi/article/details/121138176

相关推荐
zh_xuan28 分钟前
c++ 单例模式
开发语言·c++·单例模式
利刃大大3 小时前
【在线五子棋对战】二、websocket && 服务器搭建
服务器·c++·websocket·网络协议·项目
喜欢吃燃面3 小时前
C++刷题:日期模拟(1)
c++·学习·算法
SHERlocked933 小时前
CPP 从 0 到 1 完成一个支持 future/promise 的 Windows 异步串口通信库
c++·算法·promise
虚拟之4 小时前
36、stringstream
c++
我很好我还能学4 小时前
【面试篇 9】c++生成可执行文件的四个步骤、悬挂指针、define和const区别、c++定义和声明、将引用作为返回值的好处、类的四个缺省函数
开发语言·c++
南岩亦凛汀5 小时前
在Linux下使用wxWidgets进行跨平台GUI开发
c++·跨平台·gui·开源框架·工程实战教程
曦月逸霜6 小时前
第34次CCF-CSP认证真题解析(目标300分做法)
数据结构·c++·算法
galaxy_strive6 小时前
绘制饼图详细过程
开发语言·c++·qt
Unpredictable2227 小时前
【VINS-Mono算法深度解析:边缘化策略、初始化与关键技术】
c++·笔记·算法·ubuntu·计算机视觉