单例模式 C++

特点

保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享

懒汉式

特点

第一次调用才初始化 避免浪费内存
必须加锁才能保证单例 但是加锁影响效率

demo

//
// Created by xatusec on 2019/12/3.
//

//.h
#ifndef SINGLETON_SINGLETON_H
#define SINGLETON_SINGLETON_H

#include <iostream>

class Singleton
{

public:
    static Singleton * GetInstance();
private:
    Singleton();
    static Singleton *m_pInstance;
};

#endif //SINGLETON_SINGLETON_H
//.cpp
#include "Singleton.h"



Singleton *Singleton::GetInstance()
{
    if(m_pInstance == nullptr)
    {
        m_pInstance = new Singleton();
    }
    return m_pInstance;
}

Singleton::Singleton()
{
        std::cout << "Singleton()" << std::endl;
}


Singleton *Singleton::m_pInstance = nullptr;
//.main
#include "Singleton.h"
#include<iostream>
using namespace std;

int main()
{

    Singleton *p1 = Singleton::GetInstance();
    Singleton *p2 = Singleton::GetInstance();

    cout << "p1 address:"<< p1 <<endl;
    cout << "p2 address:"<< p2 << endl;
}

结果

在这里插入图片描述
两者地址相同 保证指向的是在内存中的同一个空间 实现了一个类只初始化一个实例

不重写拷贝构造/运算符重载存在问题

没有完全保证一个类只有一个实例(没有重写/禁用拷贝构造和运算符重载)改写main中的代码 结果如下

更改main.cpp为

#include "Singleton.h"

#include<iostream>
using namespace std;

int main()
{

	Singleton* p1 = Singleton::GetInstance();
	Singleton* p2 = Singleton::GetInstance();

	cout << "p1 address:" << p1 << endl;
	cout << "p2 address:" << p2 << endl;

	Singleton p3(*p1);
	Singleton p4 = *p1;

	cout << "p3 address:" << &p3 << endl;
	cout << "p4 address:" << &p4 << endl;
}

结果为
在这里插入图片描述
很明显 一个类生成了三个实例,不符合单例模式的要求

重写/删除拷贝构造个运算符重载

重写Singleton中拷贝构造函数和运算符重载

#include <iostream>

class Singleton
{
public:
	static Singleton* GetInstance();

private:
	Singleton(const Singleton& Single);
	void operator= (const Singleton& Single);
	Singleton();
	static Singleton* m_pInstance;
};

在这里插入图片描述
保险起见 删除上述函数

#include <iostream>

class Singleton
{
public:
	static Singleton* GetInstance();

private:
	Singleton(const Singleton& Single) = delete;
	void operator= (const Singleton& Single) = delete;
	Singleton();
	static Singleton* m_pInstance;
};

线程安全/内存泄漏问题

多线程下的该类可能会引发竞态条件
第一个线程正在判断全局指针是否为空,此时类尚未实例化,所以全局指针为空,其他线程到此 判断后发现指针为空,此时第一个线程才实例化了第一个类,故此,可能违背单例模式的原则,一个类实例化了多个对象出来。

解决方法

使用加锁和智能指针的改良方案

在这里插入代码片

饿汉式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章