
单例模式(Singleton Pattern)是一种常用的软件设计模式,它的主要目的是确保一个类仅有一个实例,并提供一个全局访问点来获取该实例。这种模式特别适用于管理资源、控制对共享资源的访问,或者创建一些中心控制类,如日志记录器、数据库连接池等。
单例模式(Singleton Pattern)是一种常用的设计模式,它确保一个类仅有一个实例,并提供一个全局访问点来获取这个唯一的实例。C++的单例模式的特点可以总结为以下几点:
在C++中实现单例模式时,需要特别注意构造函数、析构函数、拷贝构造函数和赋值操作符的私有化,以防止外部通过new、拷贝等方式创建或复制实例。同时,也需要考虑线程安全的问题,在需要时加入适当的同步机制。
在C++中,单例模式是一种确保一个类只有一个实例,并提供一个全局访问点来访问该实例的设计模式。单例模式有多种实现方式,每种方式都有其特定的应用场景和优缺点。以下是几种常见的C++单例模式实现方式。
getInstance()方法时创建实例。std::call_once):#include <iostream>
#include <mutex>
#include <memory>
class Singleton {
private:
Singleton() { std::cout << "Singleton constructed." << std::endl; }
static std::once_flag initInstanceFlag;
static std::unique_ptr<Singleton> instance;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton& getInstance() {
std::call_once(initInstanceFlag, []() {
instance.reset(new Singleton());
});
return *instance;
}
void someMethod() { std::cout << "Method of the singleton" << std::endl; }
~Singleton() { std::cout << "Singleton destructed." << std::endl; }
};
std::once_flag Singleton::initInstanceFlag;
std::unique_ptr<Singleton> Singleton::instance;class Singleton {
private:
static Singleton instance;
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton& getInstance() {
return instance;
}
void someMethod() { /* ... */ }
};
Singleton Singleton::instance;#include <mutex>
class Singleton {
private:
static Singleton* instance;
static std::mutex mtx;
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton* getInstance() {
if (instance == nullptr) {
std::lock_guard<std::mutex> guard(mtx);
if (instance == nullptr) {
instance = new Singleton();
}
}
return instance;
}
// 其他成员和方法...
};
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;class LazySingleton {
private:
LazySingleton() {}
class InnerHolder {
public:
static LazySingleton INSTANCE;
};
static LazySingleton& getInstance() {
return InnerHolder::INSTANCE;
}
// 禁止拷贝和赋值
LazySingleton(const LazySingleton&) = delete;
LazySingleton& operator=(const LazySingleton&) = delete;
};
LazySingleton LazySingleton::InnerHolder::INSTANCE;在多线程环境下,单例模式的实现需要确保线程安全。除了使用互斥锁等同步机制外,从C++11开始,局部静态变量的初始化被标准规定为线程安全。因此,可以使用静态局部变量来实现线程安全的单例模式,而无需显式使用互斥锁(如std::mutex)或其他同步机制。
利用C++11的线程安全局部静态变量初始化来实现单例模式是一种简洁且高效的方法。这种方法通常被称为“Meyers' Singleton”(以Scott Meyers命名,他在其著作中推广了这种方法)。
下面是一个使用C++11的线程安全局部静态变量初始化来实现单例模式的示例:
#include <iostream>
class Singleton {
private:
Singleton() {
// 构造函数,可能包含一些初始化代码
std::cout << "Singleton constructed." << std::endl;
}
// 禁止拷贝和赋值
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
// 静态成员函数,返回单例的引用
static Singleton& getInstance() {
// 局部静态变量,其初始化是线程安全的
static Singleton instance;
return instance;
}
void someMethod() {
// 单例的方法
std::cout << "Method of the singleton" << std::endl;
}
~Singleton() {
// 析构函数,可能包含一些清理代码
std::cout << "Singleton destructed." << std::endl;
}
};
int main() {
// 从多个线程访问单例
// 注意:为了简单起见,这里没有在main函数中直接创建线程
// 但在实际应用中,会从多个线程调用Singleton::getInstance()
// 访问单例
Singleton& singleton = Singleton::getInstance();
singleton.someMethod();
// 如果从多个线程调用,每个线程都会得到相同的实例
return 0;
}
在这个例子中,getInstance()函数内的static Singleton instance;声明了一个局部静态变量。根据C++11及以后的标准,这个局部静态变量的初始化是线程安全的。也就是说,即使多个线程同时调用getInstance(),它们也会看到相同的instance对象,且instance的构造函数只会被调用一次。
这种方法的好处是代码简洁且易于理解,同时避免了使用互斥锁可能带来的性能开销。然而,需要注意的是,如果单例的构造函数或析构函数中执行了复杂的操作(如动态内存分配、文件操作等),则这些操作本身可能需要额外的同步措施来确保线程安全。但在这个上下文中,我们主要关注的是单例实例的创建和访问过程的线程安全性。