单例模式
1:什么是单例
我的理解:在程序运行期间,只构造一个实例,所有的使用都共享使用该实例
2:如何实现单例
单例的特性:
1:全局唯一的对象 ==》用static成员变量或者作用域特性实现
2:不允许用户去构造 ==》禁用构造函数,但是要保证自己能调用
3:只提供相应的接口,不允许用户修改 ==》禁用相关的拷贝构造等
4:多线程要安全,资源的释放 ==》加锁,同一作用域static对象释放在程序运行结束时调用对应的析构函数
利用static特性,实现单例模式. 1:静态成员为所有对象共享,不属于某个单个实例 2:静态成员必须在类外定义,不需要加static,声明时已经加过 3:类静态成员即可用类名::静态成员或者对象.静态成员来访问 4:静态成员函数没有隐藏的this指针,不能访问任何非静态成员 5:静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值
单例的实现主要依赖static的特性实现!!!
3:编码实现
1: 在栈上控制内存的申请与释放,借助static特性(所有对象共享,不属于某个实例),实现懒汉和饿汉两种模式的单例
饿汉:
#include <iostream> using namespace std; class Singleton{ private: Singleton() = default; Singleton(const Singleton & s) = delete; Singleton &operator = (const Singleton &s) = delete; ~Singleton(){}; private: static Singleton m_sig; public: static Singleton * GetInstence() { return &m_sig; } void Print() { cout<<"Singleton Instence\n "; } }; Singleton Singleton::m_sig; //饿汉 int main() { Singleton::GetInstence()->Print(); return 0; }
懒汉: static为整个类服务,而不是某个对象,只初始化一次,而且生命周期延长到整个程序运行结束才释放,全局数据区分配内存
修饰全局变量时,只能在本文件访问
#include <iostream> using namespace std; class Singleton{ private: Singleton() = default; Singleton(const Singleton & s) = delete; Singleton &operator = (const Singleton &s) = delete; ~Singleton(){}; public: static Singleton * GetInstence() //调用这个函数的时候static生效了 { static Singleton m_sig; return &m_sig; } void Print() { cout<<"Singleton Instence\n "; } }; int main() { Singleton::GetInstence()->Print(); return 0; }
2:可以利用static的特性,申请堆内存,相关的实现如下:
如下代码,借助static管理堆内存,但明显发现,new出来的资源是没有释放的,
#include <iostream> #include <mutex> using namespace std; class Singleton{ private: Singleton() = default; Singleton(const Singleton & s) = delete; Singleton &operator = (const Singleton &s) = delete; ~Singleton(){}; public: //对静态成员操作,所以控制成static static Singleton * GetInstence() { if(Singleton::m_sig_instance == NULL) { m_mutex.lock(); if(Singleton::m_sig_instance == NULL) { m_sig_instance = new Singleton(); } m_mutex.unlock(); } } void Print() { cout<<"Singleton Instence.\n "; } private: static Singleton * m_sig_instance; static std::mutex m_mutex; }; Singleton * Singleton::m_sig_instance = NULL; std::mutex Singleton::m_mutex; int main() { Singleton::GetInstence()->Print(); return 0; }
借助static的栈内存特性和类的作用域会调用析构函数,在类的作用域内用static特性实现资源的释放:
#include <iostream> #include <mutex> using namespace std; class Singleton{ private: Singleton() = default; Singleton(const Singleton & s) = delete; Singleton &operator = (const Singleton &s) = delete; ~Singleton(){}; class FreeSingleton { public: ~FreeSingleton() { cout<<"start free singletion \n"; if(m_sig_instance != NULL) { cout<<"free singletion \n"; delete m_sig_instance; m_sig_instance = NULL; } } }; public: //对静态成员操作,所以控制成static static Singleton * GetInstence() { if(Singleton::m_sig_instance == NULL) { m_mutex.lock(); if(Singleton::m_sig_instance == NULL) { m_sig_instance = new Singleton(); } m_mutex.unlock(); } } void Print() { cout<<"Singleton Instence.\n "; } private: static Singleton * m_sig_instance; static std::mutex m_mutex; static FreeSingleton m_freed; }; Singleton * Singleton::m_sig_instance = NULL; std::mutex Singleton::m_mutex; //借助static 栈的特性,通过析构释放对应的内存 注意这里的类型和static变量的作用域取值 Singleton::FreeSingleton Singleton::m_freed; int main() { Singleton::GetInstence()->Print(); return 0; }