一、单例模式的析构函数
不要在单例模式的析构函数中释放单例
二、单例模式懒汉式和饿汉式的区别
1. 实例化:
懒汉式默认不会实例化,外部什么时候调用什么时候new。饿汉式在类加载的时候就实例化,并且创建单例对象。
2. 线程安全:
饿汉式线程安全,在线程还没出现之前就已经实例化了,因此饿汉式线程一定是安全的。
懒汉式线程不安全,因为懒汉式的是在使用时才会实例化,如果此时有多个线程都需要实例化,都进入了new方法,就会不知道到底需要返回哪一个实例,(加同步锁可以解决该问题)
3. 效率:
因为懒汉式一般需要加锁,所以在效率上懒汉式的效率更低。
4. 性能
饿汉式无论是否使用,都会在类加载的时候实例化,因此更占用空间,浪费内存。
三、C++11之后单例模式的实现
四、单例模式的单例对象(创建,初始化,销毁,static)
五、两次判空
只有懒汉式才会出现这种情况,饿汉式不需要加锁
Singleton* getInstance()
{
lock();
if (instance == NULL)
{
instance = new Singleton();
}
unlock();
return instance;
}
因为每次判断是否为空都需要被锁定,如果有很多线程的话,就会造成大量线程的阻塞,所有就有了两层锁。
Singleton* getInstance()
{
if (instance == NULL)
{ //只有为空的线程才会进入锁,这样可以避免很多不为空的线程进入,不会阻塞很多线程
lock();
if (instance == NULL)
{
instance = new Singleton();
}
unlock();
}
return instance;
}
完整代码
单例模式
#include <iostream>
using namespace std;
class A
{
public:
static A* getSingleTon()
{
//static A* m_p = NULL; //这样写每次获取单例都会调用构造函数,不建议
if (NULL == m_p)
{
m_p = new A();
}
return m_p;
}
///< 释放空间
void destroy()
{
if (m_p)
{
///< 注意多线程释放
delete m_p;
m_p = nullptr;
}
}
private:
static A* m_p; //此处声明须在类外定义
A() { std::cout << "构造
"; }
~A() { std::cout << "析构
"; }
//不要在析构函数中释放
//~A()
//{
// if (NULL != m_p)
// {
// cout << "xxx" << endl;
// delete m_p; // 递归调用析构
// m_p = NULL;
// cout << "yyy" << endl; // 永远也不会执行
// }
//}
};
A* A::m_p = nullptr;
int main()
{
A* p = A::getSingleTon();
p->destroy();
return 0;
}