【牛客带你学编程C++方向】项目练习第5期(参考答案)
参考答案:
懒汉式:
class CSingleton
{
public:
static CSingleton* GetInstance()
{
if ( m_pInstance == NULL )
m_pInstance = new CSingleton();
return m_pInstance;
}
private:
CSingleton(){};
static CSingleton * m_pInstance;
};
GetInstance()使用懒惰初始化,也就是说它的返回值是当这个函数首次被访问时被创建的。这是一种防弹设计——所有GetInstance()之后的调用都返回相同实例的指针:
CSingleton* p1 = CSingleton :: GetInstance();
CSingleton* p2 = p1->GetInstance();
CSingleton & ref = * CSingleton :: GetInstance();
对GetInstance稍加修改,这个设计模板便可以适用于可变多实例情况,如一个类允许最多五个实例。
代码很简单,但是会存在内存泄漏的问题,new出来的东西始终没有释放,下面是一种饿汉式的一种改进。
CSingleton* p1 = CSingleton :: GetInstance();
CSingleton* p2 = p1->GetInstance();
CSingleton & ref = * CSingleton :: GetInstance();
对GetInstance稍加修改,这个设计模板便可以适用于可变多实例情况,如一个类允许最多五个实例。
代码很简单,但是会存在内存泄漏的问题,new出来的东西始终没有释放,下面是一种饿汉式的一种改进。
class CSingleton
{
private:
CSingleton()
{
}
static CSingleton *m_pInstance;
class CGarbo
{
public:
~CGarbo()
{
if(CSingleton::m_pInstance)
delete CSingleton::m_pInstance;
}
};
static CGarbo Garbo;
public:
static CSingleton * GetInstance()
{
if(m_pInstance == NULL)
m_pInstance = new CSingleton();
return m_pInstance;
}
};
在程序运行结束时,系统会调用CSingleton的静态成员Garbo的析构函数,该析构函数会删除单例的唯一实例。使用这种方法释放单例对象有以下特征:
1.在单例类内部定义专有的嵌套类。
2.在单例类内定义私有的专门用于释放的静态成员。
3.利用程序在结束时析构全局变量的特性,选择最终的释放时机
1.在单例类内部定义专有的嵌套类。
2.在单例类内定义私有的专门用于释放的静态成员。
3.利用程序在结束时析构全局变量的特性,选择最终的释放时机
饿汉式:
饿汉式的特点是一开始就加载了,如果说懒汉式是“时间换空间”,那么饿汉式就是“空间换时间”,因为一开始就创建了实例,所以每次用到的之后直接返回就好了。
class CSingleton
{
private:
CSingleton()
{
}
public:
static CSingleton * GetInstance()
{
static CSingleton instance;
return &instance;
}
};
注:线程安全的通俗解释 - 不管多个线程是怎样的执行顺序和优先级,或是wait,sleep,join等控制方式,如果一个类在多线程访问下运转一切正常,并且访问类不需要进行额外的同步处理或者协调,那么我们就认为它是线程安全的。 线程安全的类应当封装了所有必要的同步操作,调用者无需额外的同步。还有一点:无状态的类永远是线程安全的。
在饿汉式的单例类中,其实有两个状态,单例未初始化和单例已经初始化。假设单例还未初始化,有两个线程同时调用GetInstance方法,这时执行 m_pInstance == NULL 肯定为真,然后两个线程都初始化一个单例,最后得到的指针并不是指向同一个地方,不满足单例类的定义了,所以饿汉式的写***出现线程安全的问题!在多线程环境下,要对其进行修改。
多线程下的单例模式
这里要处理的是懒汉模式。
这里要处理的是懒汉模式。
class Singleton
{
private:
static Singleton* m_instance;
Singleton(){}
public:
static Singleton* getInstance();
};
Singleton* Singleton::getInstance()
{
if(NULL == m_instance)
{
Lock();//借用其它类来实现,如boost
if(NULL == m_instance)
{
m_instance = new Singleton;
}
UnLock();
}
return m_instance;
}
使用double-check来保证thread safety.但是如果处理大量数据时,该锁才成为严重的性能瓶颈。
Tips:
牛客带你学编程-C++方向:【牛客带你学编程】【C++方向】0基础小白入门培养计划!
OPPO公司福利 1240人发布