单例模式如何实现?

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。在 C++ 中,可以通过将构造函数设为私有,并提供一个静态方法来获取或创建类的实例来实现单例模式。

下面是一个简单的 C++ 单例模式的实现示例:

#include <iostream>  
#include <mutex> // 用于线程安全(可选)  
  
class Singleton {  
private:  
    // 私有的静态指针,指向单例对象  
    static Singleton* instance;  
      
    // 私有的构造函数,防止外部创建实例  
    Singleton() {}  
      
    // 私有的拷贝构造函数和赋值运算符,防止拷贝  
    Singleton(const Singleton&) = delete;  
    Singleton& operator=(const Singleton&) = delete;  
  
    // 静态互斥锁(可选,用于多线程环境)  
    static std::mutex mtx;  
  
public:  
    // 静态方法,用于获取单例对象  
    static Singleton* getInstance() {  
        // 使用互斥锁保证线程安全(可选)  
        std::lock_guard<std::mutex> lock(mtx);  
  
        // 如果实例不存在,则创建它  
        if (instance == nullptr) {  
            instance = new Singleton();  
        }  
  
        return instance;  
    }  
  
    // 其他公共成员函数...  
    void doSomething() {  
        std::cout << "Singleton is doing something." << std::endl;  
    }  
  
    // 静态析构函数(可选),用于在程序结束时清理单例对象  
    // 注意:C++11 开始支持静态成员和局部对象的析构函数,但通常不推荐这样做  
    // 因为在程序结束时,所有资源都应该被自动清理  
    static void destroyInstance() {  
        if (instance != nullptr) {  
            delete instance;  
            instance = nullptr;  
        }  
    }  
  
    // 析构函数设为保护或私有的(可选),防止外部删除实例  
protected:  
    ~Singleton() {  
        // 单例对象销毁时的清理工作(如果有的话)  
    }  
};  
  
// 初始化静态成员(在类外部)  
Singleton* Singleton::instance = nullptr;  
std::mutex Singleton::mtx;  
  
// 使用示例  
int main() {  
    Singleton* s1 = Singleton::getInstance();  
    Singleton* s2 = Singleton::getInstance();  
  
    // s1 和 s2 指向同一个对象  
    if (s1 == s2) {  
        std::cout << "s1 and s2 are the same instance." << std::endl;  
    }  
  
    s1->doSomething(); // 调用单例对象的成员函数  
  
    // 在程序结束时,可以调用 destroyInstance 来清理单例对象(通常不推荐)  
    // Singleton::destroyInstance();  
  
    return 0;  
}

注意

  1. 在多线程环境中,上述示例中的 getInstance 方法不是线程安全的。为了确保线程安全,可以使用互斥锁(如 std::mutex)来保护创建实例的代码块。
  2. 在 C++11 及更高版本中,可以使用局部静态变量的方式来实现线程安全的单例模式,因为局部静态变量的初始化是线程安全的。
  3. 析构函数通常不需要设为保护或私有的,因为单例对象应该在程序结束时自动被销毁。但在某些情况下,为了防止外部代码误删单例对象,可以将析构函数设为保护或私有的。如果这样做,需要提供一个静态方法来清理单例对象(如 destroyInstance),但这通常不推荐,因为它可能导致资源泄漏或其他问题。

在 C++11 及以后的版本中,我们可以使用更简洁和线程安全的方式来实现单例模式。以下是一个基于 C++11 的线程安全单例模式的实现示例:

#include <iostream>  
#include <memory>  
#include <mutex>  
  
class Singleton {  
private:  
    // 静态成员指针,指向单例对象  
    static std::unique_ptr<Singleton> instance;  
  
    // 私有的构造函数  
    Singleton() {}  
  
    // 禁止拷贝和移动  
    Singleton(const Singleton&) = delete;  
    Singleton& operator=(const Singleton&) = delete;  
    Singleton(Singleton&&) = delete;  
    Singleton& operator=(Singleton&&) = delete;  
  
public:  
    // 静态方法,用于获取单例对象  
    static Singleton& getInstance() {  
        // 使用 std::call_once 来保证线程安全  
        static std::once_flag flag;  
        std::call_once(flag, [] {  
            instance.reset(new Singleton());  
        });  
        return *instance;  
    }  
  
    // 其他成员函数...  
    void doSomething() {  
        std::cout << "Singleton is doing something." << std::endl;  
    }  
  
    // 不需要显式销毁单例,unique_ptr 会在程序结束时自动处理  
};  
  
// 初始化静态成员(在类外部)  
std::unique_ptr<Singleton> Singleton::instance;  
  
// 使用示例  
int main() {  
    Singleton& s1 = Singleton::getInstance();  
    Singleton& s2 = Singleton::getInstance();  
  
    // s1 和 s2 引用同一个对象  
    if (&s1 == &s2) {  
        std::cout << "s1 and s2 are the same instance." << std::endl;  
    }  
  
    s1.doSomething(); // 调用单例对象的成员函数  
  
    return 0;  
}

在这个实现中,我们使用了 std::unique_ptr 来管理单例对象的生命周期,确保在程序结束时能够自动释放内存。同时,我们使用了 std::call_oncestd::once_flag 来保证 getInstance 方法的线程安全性。由于 std::call_once 保证了初始化函数只会被执行一次,因此即使多个线程同时调用 getInstance 方法,也只会有一个线程创建单例对象。

此外,我们还使用了引用 Singleton& 而不是指针 Singleton* 来返回单例对象,这样可以简化代码并减少出错的可能性。由于 std::unique_ptr 已经管理了对象的生命周期,我们不需要担心内存泄漏或其他与内存管理相关的问题。

相关推荐
菜鸟一枚在这2 小时前
深入解析设计模式之单例模式
开发语言·javascript·单例模式
FLZJ_KL2 小时前
【设计模式】【创建型模式】单例模式(Singleton)
java·单例模式·设计模式
非 白3 小时前
【Java】单例模式
java·笔记·单例模式
攻城狮7号1 天前
【第三节】C++设计模式(创建型模式)-单例模式
c++·单例模式·设计模式
Niuguangshuo1 天前
Python 单例模式笔记
笔记·python·单例模式
coooliang1 天前
Flutter 中的单例模式
javascript·flutter·单例模式
鄃鳕2 天前
单例模式【C++设计模式】
c++·单例模式·设计模式
yuanpan3 天前
23种设计模式之《单例模式(Singleton)》在c#中的应用及理解
单例模式·设计模式·c#
小突突突3 天前
总结单例模式的写法(在线程安全的情况下)
java·开发语言·后端·单例模式·java-ee
老朋友此林3 天前
详解单例模式、模板方法及项目和源码应用
java·开发语言·单例模式