单例模式
单例模式作用
1.只能创建一个对象,节约资源。
2.保证他是唯一的实例,且线程安全。
懒汉式
线程安全的懒汉式-单例模板
#include <mutex>
template <class T>
class Singleton
{
public:
static T* GetSingleton() //设计为静态成员函数:目的是在外部不用实例化对象,即可获得该单例
{
if(pSingleton == nullptr) //第一个if判断:判断单例是否创建,创建了就跳出
{
//线程锁:若同时有多个线程进入第一个if想创建对象,则需要排队。
//如果没有线程锁,同时有多个线程进入if判断,先后new了对象。前面new的对象的地址
//会被后面new的对象的地址覆盖,导致前面的new的对象造成内存泄漏。
mxt.lock();
if(pSingleton == nullptr) //排队的线程,如果已经有一个创建了后面的判断一下,就不用再创建,直接跳出。
{
pSingleton = new T();
}
mxt.unlock();
}
return pSingleton;
}
static void Destroy() //销毁单例
{
mxt.lock();
if (pSingleton != nullptr)
{
delete pSingleton;
pSingleton = nullptr;
}
mxt.unlock();
}
private:
static T* pSingleton;
static std::mutex mxt;
};
template <class T>
std::mutex Singleton<T>::mxt;
template <class T>
T* Singleton<T>::pSingleton = nullptr;
懒汉式举例
#include "Singleton/Singleton.h"
class GirlFriend
{
public:
friend class Singleton<GirlFriend>; //因为单例类的构造函数为protected/private,因此外部需要调用它需要成员它的友元类。
void show() const
{
std::cout << "身高:" << height << std::endl;
std::cout << "年龄:" << age << std::endl;
}
private:
GirlFriend() = default; //需要构建成单例的类,它的构造函数需要声明为protected/private类型,防止设计者在外部直接创建对象。即严格控制该类对象的创建方式。
~GirlFriend() = default;
int age = 18;
int height = 166;
};
main.cpp
#include <iostream>
#include "GirlFriend/GirlFriend.h"
#include "Singleton/Singleton.h"
int main() {
Singleton<GirlFriend>::GetSingleton()->show();
std::cout << "Hello, World!" << std::endl;
return 0;
}
结果
身高:166
年龄:18
Hello, World!
饿汉式
饿汉式单例的对象在程序启动时的静态初始化阶段创建(main 之前),而非编译时。 这种特性保证了多线程安全(C++11 及以上标准中,静态变量初始化是线程安全的),但可能提前占用资源(即使程序全程未使用该单例)
饿汉式代码举例
singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H
class Singleton {
public:
// 禁止拷贝构造和赋值操作
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 提供全局访问点,返回引用
static Singleton& getInstance() {
return instance;
}
// 示例成员函数
void doSomething() {
// 业务逻辑
}
private:
// 私有构造函数,防止外部实例化
Singleton() = default;
// 静态成员变量,程序启动时初始化
static Singleton instance;
};
#endif // SINGLETON_H
singleton.cpp文件
#include "singleton.h"
// 初始化静态成员变量
Singleton Singleton::instance;