C++ 设计模式(二)——单例模式

本文介绍了C++中的单例模式,包括饿汉式和懒汉式的实现,强调了它们的时间和空间效率特点。饿汉式在类加载时就创建实例,而懒汉式则在第一次调用时创建,可能涉及线程安全性问题。此外,还提到了使用QSharedPointer确保对象的唯一性,并分享了如何简化单例模式调用的个人小技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

序言

我本来我是没打算写多少设计模式的,毕竟我写得很简单,还是参考的菜鸟教程,但是竟然有人私信我想看剩下的,那好吧,确实,不会JAVA的看起来确实有点迷糊和难受(我也不会JAVA),会C++的还是看C++的方式来得舒服。

环境

Qt5.12 C++

理解

该图并不遵守UML规范,只是单纯为了便于源码快速回忆及理解

外放接口
获取唯一实例
SingleObject
+static SingleObject *instance()
+void doSomething()
-SingleObject()
«interface»
单例
+static SingleObject *instance()
Demo
+main()

示例

饿汉式单例

饿汉式顾名思义就是担心饿死,提前把资源准备好,也就是一开始提前把实例申请好。

特点是:空间换时间

singleobject.h

#include <QSharedPointer>

class SingleObject
{
public:
    /**
     * @brief 获取唯一实例
     * @return 返回指向唯一实例的指针
     */
    static SingleObject *instance();

    /**
     * @brief 表示该类需要用到的函数
     */
    void doSomething();

private:
    /**
     * @brief 单例模式时构造函数要放到私有中,防止被调用定义,以保证单例
     */
    SingleObject();

	// 保持实例的唯一性,使其无法复制和移动
	Q_DISABLE_COPY_MOVE(SingleObject)

private:
	static QSharedPointer< SingleObject> thisInstance;
};

.
singleobject.cpp

#include "singleobject.h"

static QSharedPointer< SingleObject> SingleObject::thisInstance{ new SingleObject};

SingleObject::SingleObject()
{

}

SingleObject *SingleObject::instance()
{
	return thisInstance.data();
}

.

懒汉式 / 饱汉式 单例

懒汉式或者说饱汉式,顾名思义就是懒得弄,或者饱汉不需要准备,用到的时候再申请实例,但这样有些方式会线程不安全。

特点是:时间换空间

singleobject.h

#include <QDebug>

class SingleObject
{
public:
	/**
	 * @brief 获取唯一实例
	 * @return 返回指向唯一实例的指针
	 */
	static SingleObject *instance();
	
	/**
	 * @brief 表示该类需要用到的函数
	 */
	void doSomething();

private:
	/**
	 * @brief 单例模式时构造函数要放到私有中,防止被调用定义,以保证单例
	 */
	SingleObject();
    
	// 保持实例的唯一性,使其无法复制和移动
	Q_DISABLE_COPY_MOVE(SingleObject)

private:
	//方法一:只单线程使用时简便判断,会相对来说资源消耗小,但线程不安全,可以直接放cpp上边声明定义
	static SingleObject *thisInstance;

	//方法二:为多线程使用时加锁判断,会相对来说资源消耗较多,但线程安全,可以直接放cpp上边声明定义
	static SingleObject *thisInstance;
	static QMutex mutex;
};
#include "singleobject.h"

//方法一/方法二
SingleObject *SingleObject::thisInstance = nullptr;

SingleObject::SingleObject()
{

}

SingleObject *SingleObject::instance()
{
	//方法一 线程不安全
	if (nullptr == thisInstance)
	{
		//多个线程时,会存在A判断为空进来后,还没申请内存前,B也判断为空跟着进来,结果申请多了一次内存导致内存泄露
		thisInstance = new SingleObject;
	}
	return thisInstance;

	//方法二 线程安全
	if (nullptr == thisInstance) 
	{
		QMutexLocker locker(&mutex);
		//多个线程时A线程来到这里,B虽然跟着进来了,但是A上锁了,B只能等,A申请好内存出去后B再进来判就不会空了,也就出去了,不会再次申请内存。
		if (nullptr == thisInstance)
			thisInstance = new SingleObject;
	}
	return thisInstance;

	//方法三:最推荐的单例方式,在C++中最为简便JAVA没法这样做的,线程安全
	static SingleObject thisInstance;
	return &thisInstance;

	//方法四:也可以这样用,和方法三区别不太大,消耗也是多一份智能指针,但是资源消耗放在堆上,也可以用普通的指针,只要你自行有地方释放即可
	static QScopedPointer< SingleObject > thisInstance(new SingleObject);
	return thisInstance.data();
}

.

调用的地方

SingleObject::instance()->doSomething();

.

个人小技巧

分享个人一个常使用的小技巧,有些类+实例函数调用很长,我会用宏去替换,这样就可以简短使用

singleobject.h
#define SinObj SingleObject::instance()
...

调用处:
SinObj->doSomething();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

溪渣渣_梁世华

打赏?我甚至没有任何收费的章节

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值