单例模式可以确保一个类只有一个实例,并提供一个全局访问点。
为了保证只有一个实例,需要删除这个类的拷贝构造函数和拷贝赋值运算符。此外还不允许用户进行构建这个类,因此需要把构造函数和析构函数设置为私有。单例模式分为两种:懒汉式和饿汉式。
懒汉式
懒汉式是在需要用到的情况下才初始化这个实例,示例代码如下:
#include <iostream>
class Singleton
{
public:
static Singleton& getInstance()
{
static Singleton instance;
return instance;
}
void display()
{
std::cout << "Hello from Singleton!" << std::endl;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
Singleton() {}
~Singleton() {}
};
int main()
{
Singleton::getInstance().display();
}饿汉式
饿汉式是在应用程序启动时就实例化:
#include <iostream>
class Singleton
{
public:
static Singleton& getInstance()
{
return instance;
}
void display()
{
std::cout << "Hello from Singleton!" << std::endl;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
static Singleton instance;
Singleton() {}
~Singleton() {}
};
Singleton Singleton::instance;
int main()
{
Singleton::getInstance().display();
}线程安全性
C++ 11新标准下保证了局部静态变量的线程安全性,因此下面的线程安全是基于旧标准讨论的。
懒汉式单例在第一次使用时才创建实例,因此需要特别注意线程安全性问题。多线程环境下,如果多个线程同时访问 getInstance 方法,可能会导致多个实例被创建。解决方案如下:
互斥锁
static Singleton& getInstance() {
std::lock_guard<std::mutex> lock(mutex_);
if (instance == nullptr) {
instance = new Singleton();
}
return *instance;
}双重检查锁
static Singleton& getInstance() {
if (instance == nullptr) {
std::lock_guard<std::mutex> lock(mutex_);
if (instance == nullptr) {
instance = new Singleton();
}
}
return *instance;
}总结
单例类:
构造函数析构函数私有;
拷贝构造函数和拷贝赋值运算符删除;
静态函数:
getInstance获取实例;
分为懒汉式和饿汉式,懒汉式需要注意线程安全。
评论区