一、要点
0.单例模式,顾名思义只能有一个实例对象
1.私有化构造函数:不能随便调用构造函数来实例化对象
2.删除拷贝构造函数、赋值运算符函数:确保唯一实例
3.利用静态成员变量,存储指向单例对象的指针:静态方法属于类,不属于具体的实例对象。
4.提供静态方法,在堆上获取单例对象
二、代码
耽误实例化、懒加载、懒汉式:实例在第一次利用时才会被创建
1.核心代码
- static Singleton* getInstance() {
- if (instance == nullptr) {
- instance = new Singleton(); // 只有在第一次调用时创建实例
- }
- return instance;
- }
复制代码
2.具体注释代码
- #include <iostream>
- using std::cout;
- using std::endl;
- //单例模式:要通过给的接口来创造唯一实例。
- //因此,要将构造函数私有化,并且删除拷贝构造和赋值运算符函数
- class Singleton
- {
- public:
- //静态方法,用于获取唯一的实例。静态方法属于类,而非实例对象
- //懒加载、懒汉式、延迟实例化
- static Singleton* getInstance()
- {
- if(pInstance == nullptr){
- pInstance = new Singleton();
- }
- return pInstance;
- }
- void display()
- {
- cout << "This is the Singleton instance." << "\n";
- }
- private:
- //构造函数私有化,防止外部创建对象
- Singleton()
- {
- cout << "Singleton instance created.\n";
- }
- //禁用拷贝构造和赋值运算符函数
- Singleton(const Singleton & ) = delete;
- Singleton & operator=(const Singleton &) = delete;
- //静态成员变量,存储唯一的实例
- static Singleton* pInstance;
- };
- //类外初始化静态成员变量
- Singleton* Singleton::pInstance = nullptr;
- int main()
- {
- //获取单例对象的唯一实例
- Singleton* s1 = Singleton::getInstance();
- s1->display();
- //再次获取单例对象的实例
- Singleton* s2 = Singleton::getInstance();
- s2->display();
- //验证两个指针是否指向同一个实例
- if(s1 == s2){
- cout << "Both pointer point to the same instance.\n";
- }
- return 0;
- }
复制代码 另一版
- #include <iostream>
- using std::cout;
- using std::endl;
- //单例模式:要通过给的接口来创造唯一实例。
- //因此,要将构造函数私有化,并且删除拷贝构造和赋值运算符函数
- class Singleton
- {
- private:
- //构造函数私有化,防止外部创建对象
- Singleton()
- {
- cout << "Singleton instance created.\n";
- }
- //禁用拷贝构造和赋值运算符函数
- Singleton(const Singleton & ) = delete;
- Singleton & operator=(const Singleton &) = delete;
- //静态成员变量,存储唯一的实例
- static Singleton* instance;
- public:
- //静态方法,用于获取唯一的实例
- static Singleton* getInstance()
- {
- if(instance == nullptr){
- instance = new Singleton(); //延迟实例化
- }
- return instance;
- }
- void display()
- {
- cout << "This is the Singleton instance." << "\n";
- }
- };
- //静态成员变量初始化为nullptr
- Singleton* Singleton::instance = nullptr;
- int main()
- {
- //获取单例对象的唯一实例
- Singleton* s1 = Singleton::getInstance();
- s1->display();
- //再次获取单例对象的实例
- Singleton* s2 = Singleton::getInstance();
- s2->display();
- //验证两个指针是否指向同一个实例
- if(s1 == s2){
- cout << "Both pointer point to the same instance.\n";
- }
- return 0;
- }
复制代码
3.无注释代码 (单线程时,存在线程安全问题)
- #include <iostream>
- using std::cout;
- using std::endl;
- class Singleton
- {
- public:
- static Singleton* getInstance()
- {
- if(pInstance == nullptr){
- pInstance = new Singleton();
- }
- return pInstance;
- }
- private:
- Singleton(){};
- Singleton(const Singleton & rhs) = delete;
- Singleton & operator= (const Singleton & rhs) = delete;
- static Singleton* pInstance;
- };
- Singleton* Singleton::pInstance = nullptr;
- int main()
- {
- Singleton* s1 = Singleton::getInstance();
- Singleton* s2 = Singleton::getInstance();
- if(s1 == s2){
- cout << "s1 == s2,是单例的\n";
- }else{
- cout << "s1 != s2,不是单例的\n";
- }
- return 0;
- }
复制代码
4.思量线程安全 (getInstance加锁)
- #include <iostream>
- #include <mutex>
- using std::cout;
- using std::mutex;
- using std::lock_guard;
- class Singleton
- {
- public:
- static Singleton* getInstance()
- {
- lock_guard<mutex> lock(mtx);
- if(pInstance == nullptr){
- pInstance = new Singleton();
- }
- return pInstance;
- }
- private:
- Singleton(){};
- Singleton(const Singleton & rhs) = delete;
- Singleton & operator= (const Singleton & rhs) = delete;
- static Singleton* pInstance;
- static mutex mtx; //互斥锁,确保线程安全
- };
- Singleton* Singleton::pInstance = nullptr;
- mutex Singleton::mtx;
- int main()
- {
- Singleton* s1 = Singleton::getInstance();
- Singleton* s2 = Singleton::getInstance();
- if(s1 == s2){
- cout << "s1 == s2,是单例的\n";
- }else{
- cout << "s1 != s2,不是单例的\n";
- }
- return 0;
- }
复制代码
4.1 进一步减少加锁的开销,利用双重查抄锁
- // 线程安全的 getInstance 方法,使用双重检查锁
- static Singleton* getInstance()
- {
- if(pInstance == nullptr) { // 第一次检查,无锁
- std::lock_guard<std::mutex> lock(mtx); // 加锁
- if(pInstance == nullptr) { // 第二次检查,加锁后
- pInstance = new Singleton();
- }
- }
- return pInstance;
- }
复制代码
5.开释单例资源以避免内存泄露(智能指针)
- #include <iostream>
- #include <mutex>
- #include <memory>
- using std::cout;
- using std::mutex;
- using std::lock_guard;
- using std::unique_ptr;
- class Singleton
- {
- public:
- static Singleton* getInstance()
- {
- lock_guard<mutex> lock(mtx);
- if(pInstance == nullptr){
- /* pInstance = new Singleton(); */
- pInstance = unique_ptr<Singleton>(new Singleton());
- }
- return pInstance.get();
- }
- private:
- Singleton(){};
- Singleton(const Singleton & rhs) = delete;
- Singleton & operator= (const Singleton & rhs) = delete;
- /* static Singleton* pInstance; */
- static unique_ptr<Singleton> pInstance;
- static mutex mtx; //互斥锁,确保线程安全
- };
- /* Singleton* Singleton::pInstance = nullptr; */
- unique_ptr<Singleton> Singleton::pInstance = nullptr;
- mutex Singleton::mtx;
- int main()
- {
- Singleton* s1 = Singleton::getInstance();
- Singleton* s2 = Singleton::getInstance();
- if(s1 == s2){
- cout << "s1 == s2,是单例的\n";
- }else{
- cout << "s1 != s2,不是单例的\n";
- }
- return 0;
- }
复制代码
6.饿汉式
饿汉式:在类加载时就举行实例化
- #include <iostream>
- using namespace std;
- class Singleton{
- public:
- // 提供全局访问点
- static Singleton& getInstance()
- {
- // 静态局部变量在程序启动时初始化
- static Singleton instance;
- return instance;
- }
- // 删除拷贝构造函数和赋值操作符,防止复制
- Singleton(const Singleton&) = delete;
- Singleton& operator=(const Singleton&) = delete;
- // 示例方法
- void display() const{
- cout << "Singleton::display() called on instance: " << this << endl;
- }
- private:
- // 私有构造函数
- Singleton(){
- cout << "Singleton()" << endl;
- }
- // 私有析构函数
- ~Singleton(){
- cout << "~Singleton()" << endl;
- }
- };
- int main()
- {
- // 通过getInstance获取单例对象的引用,并调用示例方法
- Singleton& s1 = Singleton::getInstance();
- s1.display();
- // 再次获取单例对象的引用,验证它们是同一个实例
- Singleton& s2 = Singleton::getInstance();
- s2.display();
- // 输出将展示s1和s2有相同的地址,说明它们是同一个实例
- return 0;
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |