C++之单例(singleton)模式
0. 简介
有时候我们在面对通用代码时候,经常会尝试着创建多个示例函数来对一个函数多次赋值,这样会损耗很多的内存空间,这对于代码来说是不利的。而单例模式可以很好的解决这个问题。但是实现一个实用的单例模式来说,这个并不容易。
1. 单例函数
1.1 饿汉模式
饿汉模式 是指单例实例在类装载时就构建,并被立即执行初始化:
public class Test {
private Test() {
}
public static Test instance = new Test();// 直接对Test构造函数进行实例化
public Test getInstance() {
return instance;
}
}
优点
1.线程安全
2.在类加载的同时已经创建好一个静态对象,调用时反应速度快
缺点
资源效率不高,可能getInstance()
永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName)
,那么这个实例仍然初始化 。如果类是多态的, 那静态成员变量初始化顺序还是没保证,下面我们将详细解释这个问题.
例如:有两个单例模式的类 ASingleton
和 BSingleton
, 某天你想在 BSingleton
的构造函数中使用 ASingleton
实例, 这就出问题了. 因为 BSingleton m_pInstance
静态对象可能先 ASingleton
一步调用初始化构造函数, 结果 ASingleton::getInstance()
返回的就是一个未初始化的内存区域, 程序还没跑就直接崩掉.
1.2 懒汉模式
懒汉式是指:单例实例在第一次被使用时构建,但延迟初始化:
class Test {
private Test() {
}
public static Test instance = null;
public static Test getInstance() {
if (instance == null) {
//多个线程判断instance都为null时,在执行new操作时多线程会出现重复情况
instance = new Test();
}
return instance;
}
}
优点:
避免了饿汉式的那种在没有用到的情况下创建事例,资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法。
缺点:
懒汉式在单个线程中没有问题,但多个线程同事访问的时候就可能同事创建多个实例,而且这多个实例不是同一个对象,虽然后面创建的实例会覆盖先创建的实例,但是还是会存在拿到不同对象的情况。解决这个问题的办法就是加锁synchonized
,第一次加载时不够快,多线程使用不必要的同步开销大。
1.3 双重模式
class Test {
private Test() {
}
public static Test instance = null;
public static Test getInstance() {
if (instance == null) {
synchronized (Test.class) {
if (instance == null) {
instance = new Test();
}
}
}
return instance;
}
}
优点
资源利用率高,不执行getInstance()就不被实例,可以执行该类其他静态方法
缺点
第一次加载时反应不快
1.4 静态内部类
class Test {
private Test() {
}
private static class SingletonHelp {
static Test instance = new Test();
}
public static Test getInstance() {
return SingletonHelp.instance;
}
}
优点
资源利用率高,不执行getInstance()不被实例,可以执行该类其他静态方法
缺点
第一次加载时反应不够快
1.5 总结:
一般采用饿汉式,若对资源十分在意可以采用静态内部类,不建议采用懒汉式及双重检测 。
2 . 设计一款完美的单例模式
这里我们选择静态内部类+模板类的组合方法来有效的对多线程程序进行单例模式设计
2.1 Best Practices
网络上存在一些简单的单例模式方法,这里先对一种简单的易懂的单例模式进行解释:
#include <iostream>
#include <cassert>
class Singleton
{
public:
static Singleton& Instance()
{
// https://blog.csdn.net/qq_34637408/article/details/71189382
static Singleton instance; // 静态实例化:
return instance;
}
public:
Singleton(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton& operator=(Singleton&&) = delete;
private:
Singleton() = default;
~Singleton() = default;
};
int main()
{
auto& a = Singleton::Instance(); //实例化
auto& b = Singleton::Instance();
assert(&a == &b);
return 0;
}
…详情请参照古月居
- 点赞
- 收藏
- 关注作者
评论(0)