c++11的三种单例模式
饿汉模式:在程序进入main
函数之前就创建出了对象,不存在多线程的竞态关系,内存需要手动释放。优点是比较简单,容易实现,缺点是不能传入参数,占内存,不管用不用都创建出该对象。
懒汉模式:在程序需要的时候才会创建出对象,存在多线程竞态关系,需要用C++11
中std::call_once
和std::once_flag
来避免竞态关系,内存需要手动释放。优点是不浪费内存,可以传入参数,缺点是实现比较复杂。
静态懒汉模式:和懒汉模式一样在程序需要的时候才会创建出对象,因为C++11
保证了局部静态变量的初始化是串行的,所以不存在多线程竞态关系,对象存在于进程虚拟内存的静态区,不需要手动释放内存。优点是实现非常容易,创建对象的过程只需要两行代码,缺点是不能传入参数,因为不同参数数量会在编译期实例化出多个不同的函数,导致单例变成"多例"。
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| #include <iostream> #include <mutex>
template<typename T> class Singleton_Hungry { private: Singleton_Hungry() = default; ~Singleton_Hungry() = default; Singleton_Hungry(const Singleton_Hungry<T>&) = delete; Singleton_Hungry(Singleton_Hungry<T>&&) = delete; Singleton_Hungry<T>& operator=(const Singleton_Hungry<T>&) = delete; Singleton_Hungry<T>& operator=(Singleton_Hungry<T>&&) = delete; public: static T* getInstance() { return m_instance; } static void destroy() { delete m_instance; m_instance = nullptr; } private: static T* m_instance; }; template<typename T> T* Singleton_Hungry<T>::m_instance = new T();
template<typename T> class Singleton_Lazy1 { private: Singleton_Lazy1() = default; ~Singleton_Lazy1() = default; Singleton_Lazy1(const Singleton_Lazy1<T>&) = delete; Singleton_Lazy1(Singleton_Lazy1<T>&&) = delete; Singleton_Lazy1& operator=(const Singleton_Lazy1<T>&) = delete; Singleton_Lazy1& operator=(Singleton_Lazy1<T>&&) = delete; public: template<typename... Args> static T* getInstance(Args&&... args) { std::call_once(m_flag, [&]() { m_instance = new T(std::forward<Args>(args)...); }); return m_instance; } static void destroy() { delete m_instance; m_instance = nullptr; } private: static T* m_instance; static std::once_flag m_flag; }; template<typename T> T* Singleton_Lazy1<T>::m_instance = nullptr; template<typename T> std::once_flag Singleton_Lazy1<T>::m_flag;
template<typename T> class Singleton_Lazy2 { private: Singleton_Lazy2() = default; ~Singleton_Lazy2() = default; Singleton_Lazy2(const Singleton_Lazy2&) = delete; Singleton_Lazy2(Singleton_Lazy2&&) = delete; Singleton_Lazy2& operator=(const Singleton_Lazy2&) = delete; Singleton_Lazy2& operator=(Singleton_Lazy2&&) = delete; public: static T* getInstance() { static T m_instance{}; return &m_instance; } };
class myTest { public: constexpr myTest(int a = 1,int b = 1)noexcept :m_a(a),m_b(b){} ~myTest(){} myTest(const myTest&)noexcept = default; myTest(myTest&& rhs)noexcept = default; myTest& operator=(const myTest&)noexcept = default; myTest& operator=(myTest&&)noexcept = default; public: void multiply() { std::cout << "a=" << m_a << " b=" << m_b <<" a*b=" << m_a * m_b << std::endl; } private: int m_a; int m_b; }; int main() { std::cout << "饿汉单例" << std::endl; myTest* pHungry1 = Singleton_Hungry<myTest>::getInstance(); pHungry1->multiply(); myTest* pHungry2 = Singleton_Hungry<myTest>::getInstance(); pHungry2->multiply(); std::cout << pHungry1 <<" "<< pHungry2 <<"\n" << std::endl; Singleton_Hungry<myTest>::destroy();
std::cout << "懒汉单例1" << std::endl; myTest* pLazy1 = Singleton_Lazy1<myTest>::getInstance(2,3); pLazy1->multiply(); myTest* pLazy2 = Singleton_Lazy1<myTest>::getInstance(); pLazy2->multiply(); std::cout << pLazy1 << " " << pLazy2 <<"\n" << std::endl; Singleton_Lazy1<myTest>::destroy();
std::cout << "懒汉单例2" << std::endl; myTest* pLazyStatic1 = Singleton_Lazy2<myTest>::getInstance(); pLazyStatic1->multiply(); myTest* pLazyStatic2 = Singleton_Lazy2<myTest>::getInstance(); pLazyStatic2->multiply(); std::cout << pLazyStatic1 << " " << pLazyStatic2 << "\n" << std::endl;
return 0; }
|