!!!单例模式是用来创建对象的。
单例模式
单例模式:保证类在内存中只有一个对象。
Q:那么如何保证类在内存中只有一个对象呢?
A:把构造方法私有;
B:在成员位置自己创建一个对象;
C:通过一个公共的方法提供访问这个对象。
注意:为了保证外界能够直接使用,加静态!而且静态成员函数只能访问静态成员变量!
(1)饿汉模式
通俗易懂的解释就是:类一加载就创建对象。
class CSingleton
{
private:
//A:为了保证类在内存中只有一个对象,将构造方法私有
CSingleton(){ }
//B:为了保证该对象的值不被修改,设置为私有
//B:为了保证静态成员函数能够访问到,设置为静态成员变量
static CSingleton *p = new CSingleton();
public:
//C:为了保证外界能够访问,定义为静态成员函数
static CSingleton * getInstance()
{
return p;
}
};
关于饿汉式:
A:饿汉式是线程安全的,可以直接用于多线程而不会出现问题;
B:饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,会占用一定的内存,相应的在调用时速度也会很快。
(2)懒汉模式
通俗易懂的解释就是:需要用到的时候,才创建对象。
class CSingleton
{
private:
CSingleton(){ }
static CSingleton *p;
public:
static CSingleton * getInstance()
{
if(p == NULL)
p = new CSingleton();
return p;
}
};
//静态成员变量需要类内声明,类外初始化。
CSingleton* CSingleton::p = NULL;
面试题:单例模式的思想是什么?请用代码实现。
(1)单例模式的思想就是保证类在内存中只有一个对象。
(2)代码实现到底使用饿汉式还是懒汉式:
在实际开发中:使用懒汉模式;(不会出现问题)
在面试中:使用饿汉模式;
A:延迟思想(用的时候才创建对象,所以第一次调用的时候可能会存在一些延时)
B:多线程安全问题(解决方法:加锁)
//加锁解决多线程引发的安全问题
static synchronized CSingleton * getInstance(){}
Q:那么为什么懒汉模式会存在线程安全问题呢?
在运行过程中可能存在这么一种情况:
多个线程去调用getInstance方法来获取CSingleton的实例,那么就有可能发生这样一种情况,当第一个线程在执行if(p == NULL)时,此时instance是为null的进入语句。在还没有执行p = new CSingleton()时(此时p是为null的)第二个线程也进入了if(p == NULL)这个语句,因为之前进入这个语句的线程中还没有执行p = new CSingleton(),所以它会执行p = new CSingleton()来实例化CSingleton对象,因为第二个线程也进入了if语句所以它会实例化Singleton对象。这样就导致了实例化了两个CSingleton对象。所以单例模式的懒汉式是存在线程安全问题的。