C++:单例模式-饿汉/懒汉

单例模式:

  • 一个类只能创建一个对象,即单例模式,该模式可以保证系统中只有一个实例,并提供一个访问它的安全局访问点,该实例被所有程序模块共享。用于管理服务器配置;

构造函数私有化/防拷贝

构造函数私有化/与防拷贝是实现懒汉饿汉的必要手段,如果你已经了然于心,请直接跳到下一部分:

  • 构造函数私有化:将类的构造函数私有,拷贝构造声明私有。防止别人拷贝在栈上生成对象。
  • 防拷贝:考虑也得限制拷贝对象,因为不限制,拷贝时可以直接调用默认构造-
    • 基于C98在:在私有类只声明拷贝构造不实现;
    • 基于C11:删除函数,“函数=delete”任何情况都不可以用;
  • 用一个具体的例子,看看它们是具体如何实现的:
    设计一个类,该类只能在堆上创建对象(只能用new去申请)
  • 将构造函数私有化,这样别人无法直接在外部创建对象,之能那个我规定好的在堆上申请空间的函数申请。使用提供一个静态成员函数,在该静态成员函数中完成堆对象的创建,防拷贝,别人也可以通过拷贝构造钻空子访问,注意基于C89的在私有类让拷贝构造只声明不实现方法若是遇到友元函数,就会出现漏洞,所以在这里我们使用C11的特性-删除函数;
class Heap{
public:
    static Heap* GetHeap(){
        return new Heap;
    }
private:
    Heap()
    {}//构造声明为私有,将不在对外开放;
    //Heap(const Heap&b);//
    Heap(const Heap&b) = delete//删除函数
};//C11

int main(){
    Heap*p1 = Heap::GeatHeap();
    return 0;
}

饿汉模式

  • 就是不管你将来用不用,启动程序时就创建一个唯一的实例对象(哇我三天没吃了,一看见吃的立马消灭!)
  • 如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提高响应速度更好。
  • 优点:简单;缺点:可能会导致启动很慢;
  • 要点:只能创建单个实例所以构造私有化/防拷贝
class Singleton{
public:
    static Singleton* GetInstance(){//获取实例;
        return &_sInstance;
    }
private:
    Singleton()
    {}
    //防拷贝;
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    static Singleton _sInstance;
};

Singleton Singleton::_sInstance;//在程序入口之前就完成单例对象初始化;
int main(){
    return 0;
}

懒汉模式

  • 需要用到该对象了再创建,(急什么,放兜里饿了再吃嘛!)
  • 如果单例对象构造十分耗时或者占用很多资源,比如加载插件,初始化网络连接,读取文件等,而可能该对象运行时不会用到,那麽也要在程序一开始就进行初始化,就会导致程序启动时非常缓慢。所以此情况使用懒汉模式(延迟加载)更好;
  • 优点:第一次使用实例时创建,启动时间短;缺点:复杂
  • 要点:防拷贝/线程安全(加锁)/double check(创建实例后,不再进行加锁解锁)提高效率/注意回收
class Singleton{
public:
    static Singleton* GetInstance(){//获取实例;
        if(nullptr ==_sInstance){//双检查:当对象已经有了,就不再进行枷锁解锁了(会有消耗,且并行会变成串行,性能下降),双检查会提高效率,减少浪费;
            m_mtx.lock();//加互斥锁,t1进去后会上锁,t2就得等到t1解锁后才行;不加若是同时检测到空,创建两个对象,就不是单例了,线程不安全;
                 if(_sInstance==nullptr){//第一次使用的时候才初始化创建;
            _sInstance=new Singleton;
          }
          m_mtx.unlock();//解锁;
       }
       return _sInstance;
    }
     class CGarbo {//实现内部类实现垃圾回收功能
    public:
        ~CGarbo(){
            if (Singleton::_sInstance)
                delete Singleton::_sInstance;
        }
    };
private:
    Singleton()
    {}
    //单例防拷贝;
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    static CGarbo Garbo;//定义一个静态成员变量,main程序结束时,系统会释放静态变量,会自动调用它的析构函数从而释放单例对象;
    static Singleton* _sInstance;//单例对象指针
    static mutex m_mtx;//加互斥锁
};

Singleton* Singleton::_sInstance=nullptr;
Singleton::CGarbo Singleton::Garbo;//初始化类对象会自动调缺省构造
mutex Singleton::m_mtx;
void func(int n){
    cout<< Singleton::GetInstance() << endl;
}
int main(){
    thread t1(func, 10);//创建多个线程
    thread t2(func, 10);
    t1.join();//本程序t等一下t1,t2,不可在t1,t2之前结束;
    t2.join();
    cout << Singleton::GetInstance() << endl;
    cout << Singleton::GetInstance() << endl;
}

yo~
yo~
如果觉得不错~
请别忘了点个赞~
Bro你的鼓励~
给我坚持的勇气~
Peace out~

你可能感兴趣的:(C/C++)