单例模式

一、单例模式的析构函数

不要在单例模式的析构函数中释放单例

二、单例模式懒汉式和饿汉式的区别

1. 实例化:

懒汉式默认不会实例化,外部什么时候调用什么时候new。饿汉式在类加载的时候就实例化,并且创建单例对象。

2. 线程安全:

饿汉式线程安全,在线程还没出现之前就已经实例化了,因此饿汉式线程一定是安全的。

懒汉式线程不安全,因为懒汉式的是在使用时才会实例化,如果此时有多个线程都需要实例化,都进入了new方法,就会不知道到底需要返回哪一个实例,(加同步锁可以解决该问题)

3. 效率:

因为懒汉式一般需要加锁,所以在效率上懒汉式的效率更低

4. 性能

饿汉式无论是否使用,都会在类加载的时候实例化,因此更占用空间,浪费内存。

三、C++11之后单例模式的实现

std::call_once

四、单例模式的单例对象(创建,初始化,销毁,static)

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;
}
原文地址:https://www.cnblogs.com/mmmmmmmmm/p/15346756.html