单例模式

本例适用于单线程!需要线程安全的例子(互斥)可看这里,写的很好。。。我网上看到new/delete/malloc是线程安全的,只要调用了多线程函数,链接的库就是支持线程安全的,看这里  ,但这并不意味着我们就不需要加锁了,因为在判断m_pLogger==0时,很有可能两个线程都同时判断为该条件true了,这和volatile没关系!知乎上这个回答挺好

#include <iostream>
using namespace std;

//xxx.h
class CLogger
{
public:

    friend CLogger* GetLogger();
    
    void info(const char* s) const
    {
        cout << s << endl;
    }

private:
    CLogger()
    {
        //初始化工作
    }
    ~CLogger()
    {
        cout << "~CLogger()" << endl;
    }
    CLogger(const CLogger&);
    CLogger& operator =(const CLogger&);

    static CLogger* GetInstance()
    {
        if(m_pLogger == NULL)
        {
            //lock here
            if (m_pLogger == NULL)
                m_pLogger = new CLogger;
            //unlock here
        }

        return m_pLogger;
    }

    static CLogger * volatile m_pLogger;
    
    class CGarBo
    {
    public:
        ~CGarBo()
        {
            cout << "~GarBo()" << endl;
            if(m_pLogger)
            {
                delete ::m_pLogger;
                m_pLogger = NULL;
            }
        }
    };
    static CGarBo m_garbo;
};

//xxx.cpp
CLogger * CLogger::m_pLogger = NULL;
CLogger::CGarBo CLogger::m_garbo;//不含这句,编译虽不会出错,但不会生成m_garbo实例!

CLogger* GetLogger()
{
    return CLogger::GetInstance();
}

//test.cpp
int main()
{
    GetLogger()->info("hello world");
    return 0;
}

 

 

也可以这样:

CLogger* GetLogger()
{
    static CLogger s_logger;
    return &s_logger;
}
/*
    初次调用该函数时,局部静态变量才初始化。而非是程序运行时(main前)就初始化。这和全局与class static变量不同~
    析构是在程序结束(main后)时,而不是该函数结束时。可通过以下测试:
    Sleep(4000);
    GetLogger();
    Sleep(4000) 
*/

如此,不在需要new/delete,也不需要嵌套类和加锁了,两个static成员变量也不需要了。

posted @ 2016-01-21 19:23  sfqtsh  阅读(219)  评论(0编辑  收藏  举报