为什么需要单例模式?
所谓“单例模式”,指的就是一个类只能有一个或者几个实例化的对象——比如说,在 Windows 或者 macOS 这样的桌面操作系统里,鼠标指针箭头有且只有一个,不能出现第二个。
**
懒汉与饿汉
单例分为两种实现方法:
- 懒汉
第一次用到类实例的时候才会去实例化
- 饿汉
单例类定义的时候就进行了实例化
懒汉模式代码:
class singleton {private:singleton(){}static singleton *p;public:static singleton *instance();};singleton *singleton::p =nullptr;singleton* singleton::instance(){if(p ==nullptr)p =new singleton();return p;}
饿汉模式代码:(**自己写代码首选这种**)
因为是定义就进行了实例化,所以会造成资源浪费
#include <iostream>class singleton {private:singleton(){std::cout << "饿汉模式构造函数" << std::endl;}static singleton *p;public:static singleton *instance(){return p;}void print(){std::cout << "you did it!" << std::endl;}};singleton *singleton::p = new singleton();int main(){singleton *pp = singleton::instance();pp->print();return 0;}
注: l懒汉模式只适合在单线程下,当多线程时,是不安全的。考虑两个线程同时首次调用instance方法且同时检测到p是nullptr,则两个线程会同时构造一个实例给p,这将违反了单例的准则。**
最终版本 (懒汉模式线程优化)
C++11下的单例模式
mutex singleton::lock_;atomic<singleton *> singleton::p;/** std::atomic_thread_fence(std::memory_order_acquire);* std::atomic_thread_fence(std::memory_order_release);* 这两句话可以保证他们之间的语句不会发生乱序执行。*/singleton *singleton::instance(){singleton *tmp = p.load(memory_order_relaxed);atomic_thread_fence(memory_order_acquire);if(tmp ==nullptr){lock_guard<mutex> guard(lock_);tmp = p.load(memory_order_relaxed);if(tmp ==nullptr){tmp =new singleton();atomic_thread_fence(memory_order_release);p.store(tmp, memory_order_relaxed);}}return p;}
如果是在unix平台的话,除了使用atomic operation外,在不适用C++11的情况下,还可以通过pthread_once来实现Singleton。
class singleton {private:singleton();//私有构造函数,不允许使用者自己生成对象singleton(const singleton &other);//要写成静态方法的原因:类成员函数隐含传递this指针(第一个参数)staticvoid init(){p =new singleton();}staticpthread_once_t ponce_;static singleton *p;//静态成员变量public:singleton *instance(){// init函数只会执行一次pthread_once(&ponce_,&singleton::init);return p;}};
参考:
https://www.bookstack.cn/read/CPlusPlusThings/68fdd6c8536795e6.md
