精华内容
下载资源
问答
  • boost库的某些组件中虽然有单例模式的实现,但不是很方便单独拿出来使用,于是我在其他人代码的基础上,改动、实现了一个线程安全的、可继承使用的单例模式模板类。编译器会实现局部静态变量的线程安全,因此该单例...

    一、前言

    boost库的某些组件中虽然有单例模式的实现,但不是很方便单独拿出来使用,于是我在其他人代码的基础上,改动、实现了一个线程安全的、可继承使用的单例模式模板类。编译器会实现局部静态变量的线程安全,因此该单例模式模板类也是线程安全的。程序会在第一次调用单例类的Inst函数的时候初始化单例对象。

    二、代码

    singleton.hpp

    #ifndef SINGLETON_HPP
    #define SINGLETON_HPP
    
    template<class T>
    class Singleton {
    public:
        static T& Inst() {
            static T instance;
            return instance;
        }
    protected:
        Singleton() {};
        ~Singleton() {};
    };
    
    #endif
    
    

    main.cpp

    #include <iostream>
    #include "singleton.hpp"
    
    class hello : public Singleton<hello> {
    public:
        void func(void) {
            std::cout << "hello~" << std::endl;
        }
    };
    
    int main(void) {
        hello::Inst().func();
        return 0;
    }
    
    
    展开全文
  • 也就是说,显示器、扫描枪、收款箱这三部分都应该有各自的,并且每个只能唯一地实例化一个对象,基于这种模式的程序设计,称为单例模式。  !!!单例模式只能创建一个对象,且该对象的生命周期伴随系统的整个...
  • c++单例模式类模板的实现

    千次阅读 2017-08-20 18:37:49
    设计模式中的单例模式有懒汉单例模式和饿汉单例模式两种,这部分内容记录在http://blog.csdn.net/qq_29344757/article/details/75575217中。 懒汉单例模式的设计步骤为: (1) 将构造函数的访问属性设置为private,...

    设计模式中的单例模式有懒汉单例模式和饿汉单例模式两种,这部分内容记录在http://blog.csdn.net/qq_29344757/article/details/75575217中。
    懒汉单例模式的设计步骤为:
    (1) 将构造函数的访问属性设置为private,不让该类中外部生成对象
    (2) 将标志指针变量初始化为NULL
    (3) 当外部需要使用对象时,调用类的静态成员函数,该函数判断:
    若标志指针变量为NULL,则动态生成对象,并且将该对象的地址赋值给标志指针变量,最后返回该对象的地址;
    若标志指针变量不为NULL,即其值等于前面生成的对象的地址,那么直接返回该标志指针
    (正是因为这个判断操作,使得懒人单例模式是一种非线程安全的设计模式)

    饿汉单例模式的设计步骤为:
    (1) 将构造函数的访问属性设置为private,不让该类中外部生成对象
    (2) 将标志指针变量初始化为动态生成的对象的地址
    (3) 当外部需要使用对象时,调用类的静态成员函数,该函数直接返回标志指针

    不论是二者中的哪一种,我们要将设计的类赋予单例模式属性时,都需要定义静态成员指针变量p和静态成员函数instance()以获得该类唯一对象的地址,这一部分可以提取出来,作为一个单例类模板:

    1. 饿汉单例类模板

    //singleton_class.h
    #ifndef __SINGLETON_CLASS_H__
    #define __SINGLETON_CLASS_H__
    
    #include <stdio.h>
    #include <iostream>
    
    template <typename T>
    class singleton
    {
    private:
        static T* p;        //标志指针
    
    public:
        static T* instance();   //得到类型为T对象的方法
    };
    
    template <typename T>
    T* singleton<T>::p = new T();   //不管外部是否要使用对象,进入main函数前就生成T对象,p指向该对象的地址
    
    template <typename T>
    T* singleton<T>::instance()
    {
        return p;
    }
    
    #endif /* __SINGLETON_CLASS_H__ */

    2. 懒汉单例模板类

    #ifndef __SINGLETON_CLASS_H__
    #define __SINGLETON_CLASS_H__
    
    #include <stdio.h>
    #include <iostream>
    
    template <typename T>
    class singleton
    {
    private:
        static T* p;
    
    public:
        static T* instance();
    };
    
    template <typename T>
    T* singleton<T>::p = NULL;  //初始化为NULL,等到外部需要到T类型类对象时再生成对象
    
    template <typename T>
    T* singleton<T>::instance()
    {
        if (NULL == p)
            p = new T();
    
        return p;
    }
    
    #endif /* __SIGLETON_CLASS_H__ */

    上面两种方式的单例模板类测试一样:

    #include "singleton_class.h"
    
    class TestCls
    {
    private:
        TestCls(){}                             //私有化构造函数,使本类不能再外部生成对象
        TestCls(const TestCls& );               //私有化拷贝构造函数,使本类不能为其它本类对象初始化
        TestCls& operator= (const TestCls& );   //私有化赋值操作符,使本类不能为其它本类对象赋值
    
        friend class singleton<TestCls>;        //singleton模板类为本类的友缘类,它才能new对象
    
    public:
        void print_this()
        {
            printf("this = %p\n", this);
        }
    };
    
    int main(void)
    {
        TestCls* s = singleton<TestCls>::instance();
        s->print_this();
    
        TestCls* s1 = singleton<TestCls>::instance();
        s1->print_this();
    
        return 0;
    }

    编译运行:
    这里写图片描述

    展开全文
  • C++单例类模板详解

    2020-08-26 04:56:09
    主要介绍了C++单例类模板,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 在实际工程中,如果一个的对象重复持有资源的成本很高,且对外接口是线程安全的,我们往往倾向于将其以单例模式管理。 此篇我们在 C++ 中实现正确的单例模式。 选型 在 C++ 中,单例模式有两种方案可选。 一是...
  • C++线程安全的饿汉单例模板类实现,可发挥功能类的多重使用方式

    背景

            首先,老生常谈一下单例模式,全局同时只允许存在一个单例对象(谨记),通过私有构造函数,提供静态的获取类实例对象接口的方式实现,分为饿汉和懒汉两种方式。饿汉:使用到的时候再通过接口去实例化(节省空间,线程不安全如多个线程同时构造此单例时,会出现多个实例);懒汉:初始化时已经创建实例,接口只用来返回(浪费内存,无线程安全问题)。但实际项目中大多场景会使用饿汉,并用的方法是解决线程安全问题。

            但是一个类在声明为单例的时候,其自身已被限制为单例类,无法具有普通类赋值拷贝等操作,在具体项目中使得声明为单例的功能类使用起来十分不灵活(比如某些处于逻辑中间的功能类,在某种情况下上层对其有部分单例类使用的需求,但也可作为一般功能类使用),此时直接声明为单例就很不方便。

            本文在工作项目的背景下设计一个单例模版本类,在编写特殊场景类时只需要声明此单例模板类为友元类,就可同时把此类当作普通类使用和部分功能单例类使用,同时使用此单例友元对象来管理类对象的生命周期,可以防止相同类对象多次析构的问题,具体见后面实例。

    单例模板类实现

            此单例采用饿汉的方式,同时引入C++11的std::once_flag对象来保证全局只存在一份此单例类,保证线程安全,具体实现见 Sington.hpp:

    /*
    * @file  Sington.hpp
    * @brief 单例模板类
    */
    
    #ifndef LM_SINGTON_H_
    #define LM_SINGTON_H_
    
    #include <mutex>
    
    template<typename T>
    class CSington
    {
    public:
    	using pointer = T*;
    
    	// 禁止空构造 拷贝复制
    	CSington() = delete;
    	CSington(const CSington&) = delete;
    	CSington& operator=(const CSington&) = delete;
    
    	static T* instance()
    	{
    		std::call_once(m_instantiated, []() {
    			pInstance = new T;
    			});
    		return pInstance;
    	}
    
    	static void destory()
    	{
    		if (pInstance)
    		{
    			delete pInstance;
    			pInstance = nullptr;
    		}
    	}
    
    private:
    	static T* pInstance;
    	static std::once_flag m_instantiated;
    };
    
    template<typename T>
    T* CSington<T>::pInstance = nullptr;
    
    template<typename T>
    std::once_flag CSington<T>::m_instantiated;
    
    #endif // !LM_SINGTON_H_
    

    饿汉单例模式的实现此处不再啰嗦,重点说说C++11的std::once_flag和std::call_once。

            C++11的std::once_flag和std::call_once的组合使用可达到当前对象只需要初始化一次,可完美处理饿汉模式的线程不安全问题。

    首先我们来看一下他两在std中的声明:

    struct once_flag
    {
        constexpr once_flag() noexcept;
        once_flag(const once_flag&) = delete;
        once_flag& operator=(const once_flag&) = delete;
    };
    template<class Callable, class ...Args>
      void call_once(once_flag& flag, Callable&& func, Args&&... args);
     
    } // std
    

            可以看到once_flag是不允许修改的,拷贝构造函数和operator=函数都声明为delete,这样防止程序员乱用。另外,call_once也是很简单的,只要传进一个once_flag,回调函数,和参数列表就可以了。实际上once_flag相当于一个锁,使用它的线程都会在上面等待,只有一个线程允许执行。如果该线程抛出异常,那么从等待中的线程中选择一个,重复上面的流程。具体的细节像我这种菜鸟目前还不是很能懂,推荐大家去看大佬的博客

    单例模板使用样例

            在定义的功能类时,只需要把套用此模板的单例类申明为友元类,包含此功能类模板的单例类就可以当作单例类来使用,非常方便,详见 MainApp.h

    /*
    * @file:  MainApp.h
    * @brief:.主程序驱动类
    */
    
    #ifndef LM_MAINAPP_H_
    #define LM_MAINAPP_H_
    
    #include <iostream>
    #include <string>
    #include <memory>
    #include "MzmProjectImp.h"
    #include "Sington.hpp"
    
    class MainApp
    {
    	friend class CSington<MainApp>;  // 关键
    public:
    	MainApp(const MainApp&) = delete;
    	MainApp& operator=(const MainApp&) = delete;
    	~MainApp();
    
    	// 初始化运行环境,加载插件等
    	static bool init();
    
    	// 反初始化
    	static void uninit();
    
    private:
    	MainApp();
    
    	void appStartLog();
    
    private:
    	std::string m_appPath;
    	std::string m_dateTime;
    
    };
    
    using CMainApp = CSington<MainApp>;
    
    #endif // !LM_MAINAPP_H_

    使用代码:

            

    
    #include "MainApp.h"
    #include <QApplication>
    #include <QDebug>
    
    int main(int argc, char* argv[])
    {
    	if (argc > 2 && "-cmd" != std::string(argv[1]))
    	{
    		qDebug() << "Invalid parameter";
    		return 0;
    	}
    
    	bool withUi = (1 == argc);
    	QApplication app(argc, argv);
    
    	if (!withUi)
    	{
    		return 0;
    	}
    
    	if (!MainApp::init())
    	{
    		CMainApp::destory();
    		return 0;
    	}
    
    	QObject::connect(&app, &QCoreApplication::aboutToQuit, []() {
    		CMainApp::destory();
    		});
    
    	return app.exec();
    }

            上面例子中CMainApp->instance()在init()函数中实现,当然对于CMainApp->instance()实例对象的使用例子中并没有提现,但这是我实战项目中截取出的代码,保证是没有问题,请童鞋们放心使用并及时指正问题。

    展开全文
  • C++11实现线程安全的单例代码和测试代码,包含singleton.h,main.cpp,希望帮助到大家。
  • C++单例模式以及C++单例类模板 在单例里,又分为了懒汉式和饿汉式,它们的区别在于创建实例的时间不同: 懒汉式 : 指代码运行后,实例并不存在,只有当需要时,才去创建实例(适用于单线程) 饿汉式 : 指代码一运行,实例...

    C++单例模式以及C++单例类模板

    在单例类里,又分为了懒汉式和饿汉式,它们的区别在于创建实例的时间不同:

    懒汉式 : 指代码运行后,实例并不存在,只有当需要时,才去创建实例(适用于单线程)
    饿汉式 : 指代码一运行,实例已经存在,当时需要时,直接去调用即可(适用于多线程)

    用法

    将构造函数的访问属性设置为private,
    提供一个GetInstance()静态成员函数,只能供用户访问唯一一个实例.
    定义一个静态成员指针,用来供用户获取
    重载 (=)赋值操作符以及拷贝构造函数,并设为private, 避免对象间拷贝,复制.
    简单单例类-懒汉式:

    class CSingleton
    {
    private:
        static CSingleton* m_pInstance;
     
        CSingleton()     //构造函数为private
        {
        } 
     
        CSingleton& operator = (const CSingleton& t);
        CSingleton(const CSingleton &);
    public:
        static CSingleton* getInstance()
        {
           if(m_pInstance==NULL)
               m_pInstance= new CSingleton(); 
           
            return m_pInstance;
        }
     
        void print()
        {
          cout<<this<<endl;   
        }
    };
     
    CSingleton* CSingleton::m_pInstance = NULL;
     
    int main()
    {
        CSingleton *p1=CSingleton::getInstance();
        CSingleton *p2=CSingleton::getInstance(); 
        CSingleton *p3=CSingleton::getInstance();
     
        p1->print();
        p2->print();
        p3->print();
     
        return 0;
    }
    

    打印结果

    0x6e2d18
    0x6e2d18
    0x6e2d18
    

    从打印结果可以看出,该指针对象指向的都是同一个地址,实现了一个类最多只能有一个实例(instance)存在.

    **注意:**由于实例(instance),在系统生命期中,都是存在的,所以只要系统还在运行,就不需要delete

    上面的懒汉式如果在多线程情况下 ,多个Csingleton指针对象同时调用getInstance()成员函数时,由于m_pInstance = NULL,就会创建多个实例出来.

    所以,在多线程情况下,需要使用饿汉实现

    class CSingleton
    {
    private:
     
        static CSingleton* m_pInstance;
     
        CSingleton()     //构造函数为private
        {
        }       
     
        CSingleton& operator = (const CSingleton& t);
        CSingleton(const CSingleton &); 
     
    public:
        static CSingleton* getInstance()
        { 
            return m_pInstance;
        }
    };
     
    CSingleton* CSingleton::m_pInstance = new CSingleton;
    

    单例类模板

    单例类模板,使用时候可以友元使用,可以继承使用。

    注意

    优先使用组合而非继承

    /************************************************************************/
    /* 名称:单例模板类                                                
    /* 说明:可把任何类包装成线程安全的全局单例类,	利用了C++11的智能指针和自解锁等	并实现自动GC。	*/
    /************************************************************************/
    
    #include <mutex>
    #include <memory>
    
    template<typename T>
    class CSingleton {
    public:
    
    	//获取全局单例对象
    	template<typename ...Args>
    	static std::shared_ptr<T> GetInstance(Args&&... args) {
    		if (!m_pSington) {
    			std::lock_guard<std::mutex> gLock(m_Mutex);
    			if (nullptr == m_pSington) {
    				m_pSington = std::make_shared<T>(std::forward<Args>(args)...);
    			}
    		}
    		return m_pSington;
    	}
    
    	//主动析构单例对象(一般不需要主动析构,除非特殊需求)
    	static void DesInstance() {
    		if (m_pSington) {
    			m_pSington.reset();
    			m_pSington = nullptr;
    		}
    	}
    
    private:
    	explicit CSingleton ();
    	CSingleton (const CSingleton &) = delete;
    	CSingleton & operator=(const CSingleton &) = delete;
    	~CSingleton ();
    
    private:
    	static std::shared_ptr<T> m_pSington;
    	static std::mutex m_Mutex;
    };
    
    template<typename T>
    std::shared_ptr<T> CSingleton<T>::m_pSington = nullptr;
    
    template<typename T>
    std::mutex CSingleton<T>::m_Mutex;
    
    #endif
    

    使用

    using namespace std;
    
    class Test{
    public:
    	Test(const string& strData) : m_strData(strData) {
    		cout << m_strData.data() << endl;
    	};
    	~Test() {
    		cout << "destory" << endl;
    	};
    
    private:
    	string m_strData;
    };
    
    auto main()->int { //等同于入口函数int main()
    	auto pTest = CSingleton <Test>::GetInstance("create");
    
    	CSingleton <Test>::DesInstance();
    
    	return 1;
    }
    
    #pragma once
    
    #include <QtCore/QCoreApplication>
    #include <QtCore/QAtomicPointer>
    #include <QtCore/QReadWriteLock>
    #include <QtCore/QMutex>
    #include <QtCore/QDebug>
    
    template<class T>
    class JSingleton
    {
    public:
        static T& getInstance(void); //获取唯一实例
    
    private:
        JSingleton();                                       //禁止外部构造函数
        JSingleton(const JSingleton<T> &);                  //禁止外部拷贝构造函数
        JSingleton<T>& operator = (const JSingleton<T>&);   //禁止外部赋值拷贝函数
        ~JSingleton();                                      //禁止外部析构函数
    
        QReadWriteLock              m_internalMutex;        //函数使用的读写锁
        static QMutex               m_mutex;                //实例互斥锁
        static QAtomicPointer<T>    m_instance;             //实例
    };
    
    //静态成员变量初始化
    template<class T>
    QMutex JSingleton<T>::m_mutex(QMutex::Recursive);       //一个线程可以多次锁同一个互斥量
    
    template<class T>
    QAtomicPointer<T>JSingleton<T>::m_instance;             //原子指针,默认初始化为0
    
    template<typename T>
    T& JSingleton<T>::getInstance(void)
    {
    #ifdef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
        if(!QAtomicPointer<T>::isTestAndSetNative())        //运行时检测
            qDebug() << QStringLiteral("Error: don's support TestAndSetNative!!!");
    #endif
        //双重检测加锁
        /*  ! testAndSetOrders 操作保证在原子操作前和后的的内存访问
        *    不会被重新排序。
        */
        if(m_instance.testAndSetOrdered(0, 0))          //第一次检测
        {
            QMutexLocker locker(&m_mutex);              //加锁
            m_instance.testAndSetOrdered(0, new T);     //第二次检测
        }
        return *m_instance/*.load()*/;
    }
    
    //调用示例: 如对于class JTest()
    //typedef JSingleton<JTest> test; //使用JTest来实例化模板
    //test::getInstance().fxxx();
    
    
    展开全文
  • 单例模式概述单例模式(Singleton),...单例模式的目的很简单,创建一个全局唯一的对象(or变量)。简单代码实现//Simple_Singleton.hclass Singleton { public: static Singleton* GetInstance() { if (!m_pSin
  • 1、简单的单例模式类 class singleton{ private: singleton(); ~singleton(); singleton(const singleton&); singleton& operator=(const singleton&); public: static singleton* GetIns...
  • c++友元模板单例模式

    2021-06-30 19:51:08
    1、定义一个单例模板类,以便于其他类可以继承 template <typename T> struct singleton { static T& Instance(); }; template <typename T> T& singleton<T>::Instance() { static...
  • C++ 单例模式 模版(Meyers‘ Singleton)

    千次阅读 2019-10-23 12:55:51
    自己实现的Meyers’ Singleton的单例模式模板类。 template<typename T> class Singleton { public: ~Singleton() = default; static T& getInstance() // Meyers' Singleton { static T instance...
  • c++单例模式模板

    千次阅读 2020-02-05 14:46:57
    所有单例直接继承此模板即可,线程安全,效率高(无所),延时构造。 #include <iostream> using namespace std; template <typename T> class Singleton { public: //外部获取单例的接口 static...
  • 1、单例模式(1)需求的提出:在架构设计时,某些在整个系统生命周期中最多只能有一个对象存在(Single,Instance)(2)问题:如何定义一个,使得这个最多只能创建一个对象?要控制的对象数目,必须对外隐藏构造...
  • C++单例模式

    2018-05-10 23:26:54
    教科书里的单例模式 简单的单例模式实现起来是很简单的:只需将的构造函数声明为private或者protect防止被外部实例化,内部保存一个private static的指针保存唯一的实例,实例动作由一个public的方法代劳,该...
  • 单例模式(Singleton Pattern)属于创建型模式...下面是一份单例模式模板类代码,通过atomic实现线程安全的懒汉式单例 template <class T> class Singleton : public NonCopyable{ //不可复制构造 private: s
  • C++单例模式: //singleton.h template<typename T> class Singleton : noncopyable { public: static T& Instance() { pthread_once(&ponce_, &Singleton::init); return *...
  • C++单例模式用法总结

    2021-06-17 17:24:04
    二、单例模式 2.1 基本概念 单例 Singleton 是设计模式的一种,其特点是只提供唯一一个的实例,具有全局变量的特点,在任何位置都可以通过接口获取到那个唯一实例; 保证一个仅有一个实例; 并提供一个访问它的...
  • 项目中多次使用单例模式后发现每次都是重复的构建单例,于是做了一个单例模式模板。 //单例模板 //delete 与 default 来自于 c++ 11 template <typename T> class Singleton { //使用默认构造和析构函数 ...
  • 单例模式的一种简单实现的模板
  • C++ 单例模式详解

    2020-01-07 15:08:49
    文章目录C++ 单例模式详解一、单例模式:二、单例的实现思路二、懒汉模式2.0三、最推荐的懒汉模式3.0单例模板的实现:写在最后 C++ 单例模式详解 一、单例模式: 什么是单例:在面向对象编程中,我们创建对象的过程...
  • C++模板实现单例模式

    千次阅读 2017-04-06 21:54:36
    单例模式的代码重复率太高,所以我就用模板来实现,提高了代码复用率
  • C++单例模式模板

    2017-04-12 21:48:04
    之前写毕业设计时用到的,现在把整个抽出来方便以后继续用,非线程完全安全,想要完全线程安全,可以调用std::mutex,给它加把锁。class CDevice { public: static CDevice &getCDeviceInstance() { //静态变量...
  • C++ 单例模板类

    千次阅读 2016-08-05 00:21:58
    单例模式(Singleton)是设计模式常见的一种,其目的...使用单例模板类可以很容易地实现单例模式。 代码如下: template class CSingleton { public: static T* Instance() { if (NULL == m_pInstance) {
  • C++单例模式详解

    2021-01-27 22:22:23
    一种常用的设计模式,一般指在一个进程中使用单例模式只允许存在一个实例化对象, 应用场景: 管理共享资源: 常见于程序配置文件,在整个程序运行期间,使用单例模式实例化对象来统一管理配置文件,该...
  • C++单例基类模板

    千次阅读 2017-01-09 14:35:03
    这是一个比较完善的c++单例基类模板,有很详细的注释。
  • 单例模式只提供私有的构造函数,私有化拷贝构造函数和赋值操作符防止复制 定义中含有一个该的静态私有对象 该提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。 2. 单例需不需要释放 单例...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,525
精华内容 4,210
关键字:

c++单例模式模板类

c++ 订阅
友情链接: xsyhjs.rar