c++ 单例模式

1.懒汉模式

在第一次用到类实例的时候才会去实例化

  • 方法1:加锁的经典懒汉实现

class singleton
{
protected:
    singleton()
    {
        pthread_mutex_init(&mutex);
    }
private:
    static singleton* p;
public:
    static pthread_mutex_t mutex;
    static singleton* initance();
};

pthread_mutex_t singleton::mutex;
singleton* singleton::p = NULL;
singleton* singleton::initance()
{
    if (p == NULL)
    {
        pthread_mutex_lock(&mutex);
        if (p == NULL)
            p = new singleton();
        pthread_mutex_unlock(&mutex);
    }
    return p;
}
  • 方法2:内部静态变量的懒汉实现

在instance函数里定义一个局部的静态实例,只在第一次运行时创建,所以也可以保证拥有唯一实例。

这里最好加上锁,如不加,可能造成线程不安全(depends on implementation: e.g. g++ will insert locks, but MSVC will not)。

class singleton
{
protected:
    singleton()
    {
        pthread_mutex_init(&mutex);
    }
public:
    static pthread_mutex_t mutex;
    static singleton* initance();
    int a;
};

pthread_mutex_t singleton::mutex;
singleton* singleton::initance()
{
    pthread_mutex_lock(&mutex);
    static singleton obj;
    pthread_mutex_unlock(&mutex);
    return &obj;
}

2.饿汉模式

在进入main函数前就已经完成对象的定义和初始化,线程安全。

但是有隐患,因为c++中对全局对象的构造顺序并没有明确的规定。假如有一个全局对象A,其构造函数里引用如下代码饿汉形式的指针,若在A构造函数构造之前以上单例并未构造出来,那就会有问题。

同时要注意,在构造函数里使用其它类的成员变量,是危险行为。

class singleton
{
protected:
    singleton()
    {}
private:
    static singleton* p;
public:
    static singleton* initance();
};
singleton* singleton::p = new singleton;
singleton* singleton::initance()
{
    return p;
}

3.单例模式的资源释放

很多情况下资源的释放是有必要的,如关闭占用的文件、断开与服务器的连接等等。

没有使用new时,只需要在析构函数中释放相关资源即可;

使用了new时,不能在析构函数中delete单例,这样会造成delete和析构函数的循环调用,可以使用以下方法:

  • 法1:写一个函数,主动delete,缺点是容易忘记调用该函数。
  • 法2:利用C++ Rall机制(resource acquisition is initialization,资源获取即初始化),没有深究到底是啥,大概就是程序在结束的时候,系统会自动析构所有的全局变量,以及所有类的静态成员变量。使用一个嵌套类,并定义一个私有的静态成员变量,在类的析构函数中delete单例指针。
class CSingleton:
{
public:
    static CSingleton * GetInstance();

protected:
    CSingleton();

private:
    static CSingleton * m_pInstance;
 
    class CGarbo // 它的唯一工作就是在析构函数中删除CSingleton的实例
    {
    public:
        ~CGarbo()
        {
            if (CSingleton::m_pInstance){
                delete CSingleton::m_pInstance;
                CSingleton::m_pInstance = nullptr;
            }
        }
    }; 
    static CGarbo Garbo; // 定义一个静态成员,在程序结束时,系统会调用它的析构函数
}

参考:

https://www.cnblogs.com/qiaoconglovelife/p/5851163.html

https://stackoverflow.com/questions/1463707/c-singleton-vs-global-static-object

https://blog.csdn.net/neubuffer/article/details/16900353

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值