设计模式的Singleton模式的分析

Singleton模式要求类只能创建一个实体对象。刚开始学习单件模式之时,在网上搜了一下,发现实现的方式有多种多样,但很多实现方式都存在着一些缺陷,如内存泄露,野指针。尤其是野指针问题不好处理,因为野指针的产生是由调用者产生的。显然,CSingleton类的设计者并不能控制调用者对操作,但却可以限制调用者的调用方式。

下面通过几种不同的Singleton模式的实现方式来分析。

1、在CSingleton类中建立一个指向CSingleton类的指针的静态变量,在用户第一次调用实体化函数时对该变量进行分配空间。该方法就存在内存泄露的问题。为了阻止调用者对CSingleton类进行实例化,要把CSingleton类的构造函数、拷贝构造函数和赋值运算符都设为私有。为了防止出现野指针,也应该阻止用户对CSingleton类的指针进行释放。
设计模式的Singleton模式的分析设计模式的Singleton模式的分析C++代码

#include "stdafx.h"#include <iostream>using namespace std;class CSingleton{private:    // 构造函数    CSingleton()    {        cout<<"CSingleton Constructor!n";    }    // 拷贝构造函数    CSingleton(const CSingleton& Src)    {        cout<<"CSingleton Copy Constructor!n";    }    // 赋值运算符    void operator=(const CSingleton& Src)    {        cout<<"CSingleton Copy Operator!n";    }    // 析构函数    ~CSingleton()    {        cout<<"CSingleton Destructor!n";    }private:    // 唯一的实体对象    static CSingleton* ms_pInstance;public:    // 获得实体对象指针    static CSingleton* GetInstance()    {        if (NULL == ms_pInstance)        {            ms_pInstance = new CSingleton();        }        return ms_pInstance;    }    // 测试函数    void Print()    {        cout<<"Print CSingleton!n";    }};CSingleton* CSingleton::ms_pInstance = NULL;int _tmain(void){    CSingleton* pSingleton1 = CSingleton::GetInstance();    pSingleton1->Print();    CSingleton* pSingleton2 = CSingleton::GetInstance();    pSingleton2->Print();    // 析构函数为私有,编译错误    // delete pSingleton1;    system("pause");    return 0;}


2、智能指针auto_ptr是防止内存泄露的有效方法,智能指针会执行动态分配内存对象的自动释放工作。因为auto_ptr在释放内存时,需要调用CSingleton类的析构函数,因此,必须把atuo_ptr设为类的友元,以保证对象内存的释放。但如果auto_ptr在外部再次获得CSingle指针的占用权,将会导致错误,而且是编译器无法检测的错误,是一个潜在的危险。
设计模式的Singleton模式的分析设计模式的Singleton模式的分析C++代码

#include "stdafx.h"#include <iostream>using namespace std;class CSingleton{private:    // 构造函数    CSingleton()    {        cout<<"CSingleton Constructor!n";    }    // 拷贝构造函数    CSingleton(const CSingleton& Src)    {        cout<<"CSingleton Copy Constructor!n";    }    // 赋值运算符    void operator=(const CSingleton& Src)    {        cout<<"CSingleton Copy Operator!n";    }    // 析构函数    ~CSingleton()    {        cout<<"CSingleton Destructor!n";    }public:    // 获得实体对象指针    static CSingleton* GetInstance()    {        static CSingleton s_Instance;        return &s_Instance;    }    // 测试函数    void Print()    {        cout<<"Print CSingleton!n";    }};int _tmain(void){    CSingleton* pSingleton1 = CSingleton::GetInstance();    pSingleton1->Print();    CSingleton* pSingleton2 = CSingleton::GetInstance();    pSingleton2->Print();    // 析构函数为私有,编译错误    // delete pSingleton1;    system("pause");    return 0;}


3、在GetInstance函数中创建一个静态变量,并把静态变量的指针返回给调用者。这种方式是我目前所了解的最优的实现方法,既没有内存泄露,也没有野指针的现象。但是,该方式在VC6.0下时编译不过的,是VC6.0的一个bug。还好现在,我已经升级到了VS2010。经过VS2010测试,可以顺利通过。估计VS2003以后的版本就能支持,但未具体测试过。
设计模式的Singleton模式的分析设计模式的Singleton模式的分析C++代码

#include "stdafx.h"#include <iostream>#include <memory>using namespace std;class CSingleton{public:    friend class auto_ptr<CSingleton>;private:    // 构造函数    CSingleton()    {        cout<<"CSingleton Constructor!n";    }    // 拷贝构造函数    CSingleton(const CSingleton& Src)    {        cout<<"CSingleton Copy Constructor!n";    }    // 赋值运算符    void operator=(const CSingleton& Src)    {        cout<<"CSingleton Copy Operator!n";    }    // 析构函数    ~CSingleton()    {        cout<<"CSingleton Destructor!n";    }private:    // 唯一的实体对象    /*static CSingleton* ms_pInstance;*/    static auto_ptr<CSingleton> m_apInstance;public:    // 获得实体对象指针    static CSingleton* GetInstance()    {        if (!m_apInstance.get())        {            m_apInstance.reset(new CSingleton());        }        return m_apInstance.get();    }    // 测试函数    void Print()    {        cout<<"Print CSingleton!n";    }};auto_ptr<CSingleton> CSingleton::m_apInstance;int _tmain(void){    CSingleton* pSingleton1 = CSingleton::GetInstance();    pSingleton1->Print();    CSingleton* pSingleton2 = CSingleton::GetInstance();    pSingleton2->Print();    // 析构函数为私有,编译错误    // delete pSingleton1;    // 编译器无法检测的错误,多次释放内存    // auto_ptr<CSingleton> apSingleton(pSingleton1);    system("pause");    return 0;}

原文链接: https://www.cnblogs.com/xianyunhe/archive/2011/07/04/2097503.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/28090

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午5:39
下一篇 2023年2月8日 上午5:40

相关推荐