您备案的网站名称没有关联性,柳州城市的城乡建设管理局网站,哪些网站做电商比较好,wordpress首页全部显示内容单例模式#xff08;Singleton Pattern#xff09;是一种设计模式#xff0c;确保一个类只有一个实例#xff0c;并且提供全局访问点。实现单例模式的关键是防止类被多次实例化#xff0c;且能够保证实例的唯一性。常见的实现手法包括懒汉式、饿汉式、线程安全的懒汉式等。…单例模式Singleton Pattern是一种设计模式确保一个类只有一个实例并且提供全局访问点。实现单例模式的关键是防止类被多次实例化且能够保证实例的唯一性。常见的实现手法包括懒汉式、饿汉式、线程安全的懒汉式等。
1. 饿汉式Eager Initialization
饿汉式单例在程序启动时就创建实例并且保证只有一个实例。适用于单例实例比较简单、没有资源消耗问题的情况。
class Singleton {
public:// 提供静态的访问方式static Singleton getInstance() {return instance; // 直接返回静态实例}private:Singleton() {} // 构造函数私有化防止外部创建实例~Singleton() {}Singleton(const Singleton) delete; // 禁止拷贝构造函数Singleton operator(const Singleton) delete; // 禁止赋值static Singleton instance; // 静态实例程序启动时创建
};// 静态实例必须定义在类外
Singleton Singleton::instance;注意 Singleton Singleton::instance;应在类的实现文件.cpp 文件中定义。如果静态成员变量的定义如 Singleton Singleton::instance;也放在头文件中由于头文件可能被多个源文件包含就会导致多重定义错误。
优点
简单直接保证了类的实例唯一。实例在程序启动时就被创建不会受到多线程的影响。
缺点
无法延迟实例化。即使单例没有被使用实例也会在程序启动时创建可能会浪费资源。 在饿汉式单例中实例在程序启动时就被创建因此你无需显式地调用 getInstance() 来创建对象。它是静态的并且一开始就存在。你只能通过 getInstance() 方法来访问该实例。
以下是如何在代码中调用饿汉式单例的示例
完整代码示例
#include iostream
using namespace std;class Singleton {
public:// 提供静态的访问方式static Singleton getInstance() {return instance; // 直接返回静态实例}void showMessage() {cout Singleton instance is working! endl;}private:Singleton() { cout Singleton Constructor Called! endl; } // 构造函数私有化~Singleton() { cout Singleton Destructor Called! endl; }Singleton(const Singleton) delete; // 禁止拷贝构造函数Singleton operator(const Singleton) delete; // 禁止赋值static Singleton instance; // 静态实例程序启动时创建
};// 静态实例必须定义在类外
Singleton Singleton::instance;int main() {// 通过调用 getInstance 来获取单例实例Singleton s1 Singleton::getInstance();s1.showMessage();// 由于我们不能复制实例以下代码会编译错误// Singleton s2 Singleton::getInstance(); // 编译错误不能复制单例// 单例是全局唯一的只能通过 getInstance() 获取return 0;
}代码解析 静态实例定义 static Singleton instance; 在类内部声明了一个静态的实例该实例在程序启动时被创建。静态变量 instance 的生命周期从程序开始直到程序结束所以它是全局唯一的。 getInstance() 方法 static Singleton getInstance() 提供了一个全局的访问点用来获取唯一的实例。这个方法返回一个对静态成员 instance 的引用。 在 main() 中的使用 在 main() 函数中我们通过 Singleton::getInstance() 获取了单例实例并调用了实例的方法 showMessage()。单例实例的构造函数在第一次调用 getInstance() 时自动执行但我们并没有显式地创建 Singleton 对象。
输出
Singleton Constructor Called!
Singleton instance is working!注意事项
全局唯一Singleton::getInstance() 返回的是同一个对象所以每次调用 getInstance() 都会得到相同的实例。构造函数构造函数只在第一次调用 getInstance() 时执行一次因此 Singleton Constructor Called! 只会打印一次。禁止复制拷贝构造函数和赋值运算符被删除避免了实例的复制。编译时如果尝试复制单例实例如 Singleton s2 Singleton::getInstance();会导致编译错误。
总结
通过 Singleton::getInstance() 方法获取单例实例这是调用饿汉式单例的标准方式。由于饿汉式实例在程序启动时就被创建所以你不需要显式地进行实例化操作。 2. 懒汉式Lazy Initialization
懒汉式是在需要实例时才创建实例这样可以延迟实例化提高资源的使用效率。基本实现没有线程安全多个线程同时访问时可能会出现问题。
class Singleton {
public:static Singleton* getInstance() {if (instance nullptr) {instance new Singleton();}return instance;}private:Singleton() {} // 构造函数私有化~Singleton() {}Singleton(const Singleton) delete; // 禁止拷贝构造函数Singleton operator(const Singleton) delete; // 禁止赋值static Singleton* instance;
};// 静态实例初始化为空指针
Singleton* Singleton::instance nullptr;优点
实例化延迟只有在第一次使用时才创建实例避免了不必要的资源消耗。
缺点
不是线程安全的。在多线程环境下可能会创建多个实例。 3. 线程安全的懒汉式
为了确保线程安全可以使用互斥锁mutex来同步访问确保只有一个线程能够创建实例。
#include mutexclass Singleton {
public:static Singleton* getInstance() {if (instance nullptr) {std::lock_guardstd::mutex lock(mutex); // 加锁确保线程安全if (instance nullptr) {instance new Singleton();}}return instance;}private:Singleton() {} // 构造函数私有化~Singleton() {}Singleton(const Singleton) delete; // 禁止拷贝构造函数Singleton operator(const Singleton) delete; // 禁止赋值static Singleton* instance;static std::mutex mutex; // 互斥锁
};// 静态实例初始化为空指针
Singleton* Singleton::instance nullptr;
std::mutex Singleton::mutex;优点
线程安全保证在多线程环境下只有一个实例被创建。
缺点
使用互斥锁增加了性能开销尤其是频繁访问 getInstance() 时。 4. 双重检查锁Double-Checked Locking
双重检查锁定是懒汉式的优化版本它减少了锁的使用频率。在第一次检查时不加锁只有当实例为 nullptr 时才加锁这样可以避免每次调用 getInstance() 时都进行加锁操作。
#include mutexclass Singleton {
public:static Singleton* getInstance() {if (instance nullptr) {std::lock_guardstd::mutex lock(mutex); // 加锁if (instance nullptr) { // 双重检查instance new Singleton();}}return instance;}private:Singleton() {} // 构造函数私有化~Singleton() {}Singleton(const Singleton) delete; // 禁止拷贝构造函数Singleton operator(const Singleton) delete; // 禁止赋值static Singleton* instance;static std::mutex mutex; // 互斥锁
};// 静态实例初始化为空指针
Singleton* Singleton::instance nullptr;
std::mutex Singleton::mutex;优点
提供了线程安全的懒汉式实现且避免了每次都加锁的性能开销。
缺点
代码相对复杂需要小心实现。对 instance 的访问需要特别注意线程间的同步。 5. 静态局部变量最推荐的实现方式
使用静态局部变量来实现单例模式这种方式是线程安全的并且实现简单。C11标准及以上可以确保静态局部变量的初始化是线程安全的。
class Singleton {
public:static Singleton getInstance() {static Singleton instance; // 静态局部变量return instance;}private:Singleton() {} // 构造函数私有化~Singleton() {}Singleton(const Singleton) delete; // 禁止拷贝构造函数Singleton operator(const Singleton) delete; // 禁止赋值
};优点
简洁、线程安全。在程序启动时不会立即创建实例而是等到第一次使用时创建。不需要显式加锁。
缺点
只适用于需要在第一次使用时实例化的情况。 总结
饿汉式简单适合不需要延迟初始化的场景程序启动时就创建实例。懒汉式适合需要延迟初始化的场景但需要考虑线程安全。线程安全懒汉式通过加锁保证线程安全但可能带来性能开销。双重检查锁线程安全减少了加锁的频率但实现复杂。静态局部变量线程安全简洁现代 C 中推荐的单例实现方式。
在现代 C 中静态局部变量是实现单例模式的首选方法既保证了线程安全又没有性能开销是最优选择。