C++实现Singleton设计模式

C++笔记之单例通过GetInstance传递参数 的实例,这样就能够调用私有的构造函数。在这个示例中,通过直接使用。 阅读详情

这个设计模式主要目的是想在整个系统中只能出现一个类的实例。,比如你的软件的全局配置信息,或是一个主控类,等等。


// Singleton.h

// C++:最简单的方式实现Singleton设计模式

#include <string>

#include <iostream>

using namespace std;

class Singleton

{

private:

         Singleton()                                            // private构造函数

         {

                   cout << "Singleton::Constructor" << endl;

         }

 

         static Singleton* sg;                               // 私有静态变量,其类型为Singleton*

                                                                     // 形如Singleton sg;这样的声明会出编译时错误

public:

         static Singleton* getInstance()                 // public成员函数getInstance()

         {

                   cout << "Singleton::getInstance" << endl;

                   if(!sg)

                   {

                            sg = new Singleton();           // (1)在这个地方new了一个对象,但是在什么地方delete呢?

                   }

 

                   return sg;

         }

};

 

// 测试Singleton的代码:Singleton.cpp

#include "Singleton.h"

// 用下面的方式对静态私有成员变量sg进行初始化,此时sg不指向任何对象

Singleton* Singleton::sg = 0;

int main(void)

{

         Singleton *sg = Singleton::getInstance();

 

         return 0;

}

 

关于如何在一个类的定义中,使用类本身作为类型对成员变量进行声明的详细情况,请见:

http://blog.youkuaiyun.com/pathuang68/archive/2009/11/24/4866945.aspx

 

上面的Singleton的实现至少存在一个问题:

语句(1)中new了一个对象,但没有被delete,因此肯定会造成内存泄漏。而在Java语言中由于有内存回收机制,所以不存在这个问题。不过既然是Singleton,通常都是和应用程序的生命周期是基本一致的,因此,实践中可以不考虑这个“内存泄露”问题,因为它根本没有机会造成真正意义上的泄露;另一方面,从纯技术的完备性角度来看,我们则需要解决这样的问题。

 

三、使用auto_ptr来解决内存泄漏问题

关于auto_ptr的原理和使用方法,请参考:

http://blog.youkuaiyun.com/pathuang68/archive/2009/11/29/4898101.aspx

http://blog.youkuaiyun.com/pathuang68/archive/2009/11/29/4900321.aspx

 

// Singleton.h

#include <memory>

#include <string>

#include <iostream>

using namespace std;

 

// C++:使用auto_ptr实现Singleton设计模式

class Singleton

{

private:

         Singleton()                                                                                 // private构造函数

         {

                   cout << "Singleton::Constructor" << endl;

         }

 

         static auto_ptr<Singleton> sg;                                                     // 私有静态变量,其类型为auto_ptr<Singleton>

 

public:

         static auto_ptr<Singleton> getInstance()                                       // public成员函数getInstance()

         {                                                                                                // 返回类型为auto_ptr<Singleton>

                   cout << "Singleton::getInstance" << endl;

                   if(!sg.get())                                                                        // 判断sg所指的对象是否为空

                   {

       // 此处不能直接写成auto_ptr<Singleton> sg(new Singleton);

                            auto_ptr<Singleton> temp(new Singleton);

                            sg = temp;                                             

                   }

 

                   return sg;

         }

};

 

// Singleton.cpp:测试Singleton的代码

#include "Singleton.h"

 

// 用下面的方式对静态私有成员变量sg进行初始化,此时sg不指向任何对象

auto_ptr<Singleton> Singleton::sg;

int main(void)

{

         // singleton就是我们需要的对象

         auto_ptr<Singleton> singleton(Singleton::getInstance());

 

         return 0;

}

 

这样以来,由于引入了auto_ptr,因此不会存在内存泄漏问题。进一步地,我们还可以将Singleton类,写成模板类,这样就可以更加灵活了。为此,我们另外增加一个类Student用来测试,Singleton模板类。

// Singleton.h

#include <memory>

#include <string>

#include <iostream>

using namespace std;

 

class Student

{

public:

         Student(const string name = "Andrew", const int age = 7) : name(name), age(age)

         {

                   cout << "constructor..." << endl;

         }

 

         void print_info() const

         {

                   cout << "Name: " << name << ", Age: " << age << endl;

         }

private:

         string name;

         int age;

};

 

// Singleton模板类

template<typename T>

class Singleton

{

private:

         Singleton()                                                                                           // private构造函数

         {

                   cout << "Singleton::Constructor" << endl;

         }

 

         static auto_ptr<T> sg;                                                                          // 私有静态变量,其类型为auto_ptr<T>

 

public:

         static auto_ptr<T> getInstance()                                                           // public成员函数getInstance()

         {                                                                                                         // 返回类型为auto_ptr<T>

                   cout << "Singleton::getInstance" << endl;

                   if(!sg.get())                                                                                // 判断sg所指的对象是否为空

                   {

                            // 此处不能直接写成auto_ptr<T> sg(new T);

                            auto_ptr<T> temp(new T);        

                            sg = temp;                                             

                   }

 

                   return sg;

         }

};

 

 

// Singleton.cpp 测试代码

#include "Singleton.h"

// 用下面的方式对静态私有成员变量sg进行初始化,此时sg不指向任何对象

auto_ptr<Student> Singleton<Student>::sg;

 

int main(void)

{

         auto_ptr<Student> singleton(Singleton<Student>::getInstance());

         singleton->print_info();

 

         return 0;

}

经过测试,上面的代码证明是可行的。

 

 

四、使用boost::mutex来解决线程安全性问题

在Java代码中,有一个synchronized关键字,这个关键字的作用就是确保线程安全,很明显上面的代码尽管解决了内存泄漏的问题,但决线程安全方面的问题依然存在。

 

在C++语言中,本身并不存在线程的概念,需要借助一些函数库才能实现,这种函数库有很多,其中一个比较出色的就是boost中的线程库了。boost库本身是可以跨操作系统平台的。

 

参考下面的代码和注释:

// Singleton.h

#include <memory>

#include <string>

#include <iostream>

#include <boost/thread/thread.hpp>

#include <boost/thread/mutex.hpp>

using namespace std;

 

boost::mutex sglt_mutex;

 

class Student

{

public:

         Student(const string name = "Andrew", const int age = 7) : name(name), age(age)

         {

                   cout << "constructor..." << endl;

         }

 

         void print_info() const

         {

                   cout << "Name: " << name << ", Age: " << age << endl;

         }

private:

         string name;

         int age;

};

 

 

template<typename T>

class Singleton

{

private:

         Singleton()                                                                                           // private构造函数

         {

                   cout << "Singleton::Constructor" << endl;

         }

 

         static auto_ptr<T> sg;                                                                           // 私有静态变量,其类型为auto_ptr<T>

 

public:

         static auto_ptr<T> getInstance()                                                             // public成员函数getInstance()

         {                                                                                                           // 返回类型为auto_ptr<T>

                   // 加锁,只有当前线程可以获取sg,其他线程均被阻塞(block)

                   // 直到当前线程执行sglt_mutex.unlock()

                   sglt_mutex.lock();                                                                         // (1)

                   cout << "Singleton::getInstance" << endl;

                   if(!sg.get())                                                                                  // 判断sg所指的对象是否为空

                   {

                            // 此处不能直接写成auto_ptr<T> sg(new T);

                            auto_ptr<T> temp(new T);        

                            sg = temp;                                             

                   }

 

                   return sg;

                  

         }

};

 

// Singleton.cpp

#include "Singleton.h"

 

// 用下面的方式对静态私有成员变量sg进行初始化,此时sg不指向任何对象

auto_ptr<Student> Singleton<Student>::sg;

 

void getSingletonInstanceAndDoSomeTediousWork()

{

         auto_ptr<Student> singleton(Singleton<Student>::getInstance());

 

         // 取得相关对象后,进行各种必要的运算:

         singleton->print_info();

         // .... do something else

 

         // 工作做完后,解锁。以便让别的线程获得机会。

         sglt_mutex.unlock();                                      // (2)

         // 如果没有上面这一句,则第一个获得锁的线程会无限时地阻止后续线程的运行

}

 

int main(void)

{

         boost::thread threadA(getSingletonInstanceAndDoSomeTediousWork);

         boost::thread threadB(getSingletonInstanceAndDoSomeTediousWork);

         boost::thread threadC(getSingletonInstanceAndDoSomeTediousWork);

         boost::thread threadD(getSingletonInstanceAndDoSomeTediousWork);

 

         threadA.join();

         threadB.join();

         threadC.join();

         threadD.join();

 

         return 0;

}

 

上面程序的结果如下:

Singleton::getInstance

constructor...

Name: Andrew, Age: 7

Singleton::getInstance

constructor...

Name: Andrew, Age: 7

Singleton::getInstance

constructor...

Name: Andrew, Age: 7

Singleton::getInstance

constructor...

Name: Andrew, Age: 7

 

上述结果符合预期。每次只能有一个线程,拥有对象,其他的则被阻塞,直到当前拥有锁的线程将锁解开。

 

如果函数getSingletonInstanceAndDoSomeTediousWork中的语句(2)被注释掉,那么输出结果将是:

Singleton::getInstance

constructor...

Name: Andrew, Age: 7

然后就是无限时的阻塞。

 

进一步地,如果将类Singelton定义中的(1)的这一句,即sglt_mutex.lock();也注释掉,那么输出的结果将是:

Singleton::getInstanceSingleton::getInstanceSingleton::getInstance

 

constructor...constructor...

constructor...Name: Name: Name: AndrewName: AndrewAndrew, Age: Andrew, Age: , Age: 7, Age: 77

这显然是没有同步了。因此,这不是我们所需要的。


本文转载自:http://patmusing.blog.163.com/blog/static/135834960201002322226231/

Shiro:实验性 C++ 库 #四郎 Shiro 是 C++14 或更高版本的实验库。 ##支持的编译器 gcc4.9 叮当3.5 ##用法###元组 shiro::tuple 是一个元组实用程序,它具有像 std::tuple 这样的接口。 假设用于复杂的元编程等。它的操作的递归深度受到限制,因此它可以处理很多参数。 # include < shiro> constexpr auto ct = shiro::make_tuple( 1 , ' a ' , true , /* arguments... */ , 0 ); static_assert (shiro::get< 0>(ct) == 1, ""); static_assert (shiro::get< 1>(ct) == 'a', ""); static_assert (shiro::get< 2>(ct) == true 立即下载

相关推荐

QTest 单元测试框架及单元测试思考

qt 单元测试框架 QTEST 及思考

一个老菜鸟的学习分享 1万+

C++单例模式:GetInstance()用法

GetInstance()用法,与new初始化的区别

qq_42186314的博客 7969

【项目实战】小智AI MCP协议在IoT设备控制中的深度应用解析

本文深度解析小智AI MCP协议在IoT设备控制中的应用实践。通过MCP协议作为AI与物联网设备的翻译桥梁,实现大语言模型与ESP32等硬件的无缝通信。文章详细介绍了环境搭建、工具注册、消息路由机制,并以语音控制RGB灯光系统为例展示完整开发流程,为AIoT开发者提供实用指南。

oauth7security的博客 824

单例设计模式getInstance()

对象的实例化方法,也是比较多的,最常用的方法是直接使用new,而这是最普通的,如果要考虑到其它的需要,如单实例模式,层次间调用等等。 直接使用new就不可以实现好的设计好,这时候需要使用间接使用new,即getInstance方法。这是一个设计方式的代表,而不仅仅指代一个方法名。 1. new的使用: 如Object obj = new Obje...

dianbiao2276的博客 436

太速科技-基于DSP TMS320C6678+FPGA XC7V690T的6U VPX信号处理卡

当多块盘并行工作时,存储阵列读写带宽成指数增长,2块盘则≥4GB/s,4块盘则≥8GB/s,以此类推。存储阵列的存储容量由单盘配置决定,目前单块NVME存储盘存储容量可选择512GB、1TB、2TB、4TB、8TB、16TB。硬盘管理通过文件系统,FPGA的PCIeX4与 6U VPX主板互联,操作系统直接映射管理硬盘,也可以通过前面板QSFP+ 光纤导出给其他服务器设备。本方案优势就是集中的进行采集,存储,计算一体化,降低硬件成本、功耗,减小设备体积、重量。信号处理,无线电通信领域。

Orihard_的博客 678

缺陷检测:使用PatchCore训练自己的数据集

必须包含有训练图片(无缺陷图片)、测试图片(缺陷图片)和ground_truth,并且ground_truth必须与对应图片的名称相同。同上一篇结果一样,我的输出为原始图片大小,但是不知道是不是因为图片不是正方形的,导致训练结果不好。编写一个脚本,重新规划数据集的路径规则,但是我稍微写复杂了一点,使用了类来操作。第二种(复杂):编写一个自己的Dataset,参考。第一种(简单):将数据集路径规则改成项目中。返回的必须是一个字典类型,可以阅读。本人此次使用的是第一种方法。运行时,参数部分直接输入。

xiaoxTai的博客 6473

C++ --- GetInstance()的使用

GetInstance()

yaowang_xingkong的博客 1097

C/C++ 计算程序运行的时间

C/C++计算程序执行时间的方法,精度依次增加,推荐度也依次增加 1.#include <time.h> clock_t start, finish; double process_interval ; start=clock(); process(); //要计时的程序 finish=clock(); process_interval =(double)(finish-star...

stu_shanghui的博客 1020

C++学习(3)

拷贝构造函数 Person(constPerson&P) PersonP1(P2)或PersonP1=Person(P2) 不能用拷贝构造函数初始化匿名对象 若Person(P1)等价于PersonP1;写到右值可以做拷贝构造函数 拷贝构造函数调用时机 用已经创建好的对象来初始化新的对象 以值传递的方式给函数参数传值 以值得方式返回局部对象 构造函数的调用规则 若自己提供了有参构造函数,那么系统不会提供默认构造函数;但还会提供拷贝构造函数,进行简单的值拷贝,系统默认给...

weixin_57289347的博客 648

android6 usb默认文件管理,不弹RSA配对提示框

本文修改针对 高通 Android6.0.1 出user版本时 https://www.cnblogs.com/Jokeyyu/p/7424262.html http://blog.youkuaiyun.com/sinc00/article/details/44957943 diff --git a/frameworks/base/packages/SystemUI/src/com/android...

木叶风的博客 690

32位快速加法器设计

32位快速加法器设计

好好学习,天天向上 3289

C++设计模式:Singleton的模板实现之一

题目:C++设计模式:Singleton的模板实现之一类型:原创作者:古斌亮时间:2002.12.25EMail : KingLinux@163.com  在http://www.youkuaiyun.com/ 和天极网 看了两篇关于设计模式:Singleton的C++实现的文章,自觉的学到不少东西(:)),在这里我也写了一个C++模板的实现之一,望各位大虾多多指教,也希望可以达到抛砖引玉的作用.

野草的专栏 1874

利用CAT12做皮层指标的统计分析及可视化笔记记录

利用CAT12做皮层指标的统计分析及可视化 文章目录利用CAT12做皮层指标的统计分析及可视化前言一、统计步骤1.Basic Models2.Estimate Surface Models3.Results二、可视化1.t值可视化2.p值可视化 前言 本来没有打算做SBM的,因为自己是新手小白,许多操作都不太懂,但最后还是打算做一下,于是就从上周末开始将很久之前跑VBM得到的surf文件夹中的数据捡起来继续做皮层分析,因为之前看了一个博主的博客,关于如何做SBM已经讲得非常清楚了,但是在统计及可视化这里,我

weixin_52073820的博客 8094

singleton设计模式,c++实现

singleton设计模式就是实现对象只能new一次         #include class base { private: base() { // std::cout<<"hello world"<<std::endl; str = "hello world"; // me = NULL; } public: char* str; priv

paul08colin 1360

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

招聘搜索列表一进去,发布时间就能看清:boss-show-time

求职者在搜索列表页里,每张卡片只写"本周发布""近期",岗位到底是昨天的还是两个月前的,分辨不出来。boss-show-time 把精确的发布时间写回 Boss 直聘、智联招聘、前程无忧、拉勾招聘四个平台的列表卡片,并按发布早晚着色,同时记下你第一次看到每个职位的时刻。 ## 它能替你做什么 **一眼分辨岗位新旧**。时间标签位于卡片右上方,背景色随发布天数变化:7 天内绿、8~14 天浅绿、

gitblog_00789的博客 147

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

C++设计模式:Singleton的模板实现之一 (转)

C++设计模式:Singleton的模板实现之一 (转)[@more@]题目:C++设计模式:Singleton的模板实现之一类型:原创 作者:古斌亮时间:2002.12.25EMail : Linux@163.com"&gt...

ciya3282的博客 202

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

设计模式C++实现_1_Singleton设计模式(简单的实现)

Singleton设计模式 思路如以下: Single.h #pragma once #include &lt;iostream&gt; #include &lt;string&gt; using namespace std; class Single { public: static Single&amp; Instance(void) ...

weixin_34406796的博客 145

C++实现设计模式之 —— 单例模式 Singleton

单例模式是最简单的创建型模式,当某个类只需要唯一的一份实例时,使用单例模式可以确保不会创建多余的实例。在C++ 中,单例模式可以避免全局变量的使用。下面是一个典型的线程安全的单例模式 #ifndef Singleton_h__ #define Singleton_h__ #include //C++11 class CSingleton { public: static CSinglet

Fire_Lord的专栏 698

【设计模式】Singleton模式C++实现

Singleton是设计模式中比较简单的一个。园中的朋友们应该都很熟悉了。前段时间参加xxx外企的面试,和面试官讨论C++的时候正好写了一个。当时由于在有些地方考虑不太周全,代码出现了一些疏漏。不过最终写出了合格的实现。 Singleton模式 要求: 1、保证类只有一个实例 2、实例只能由类自身构造 3、必须为其他所有对象提供这一对象以访问。 由此

Stay hungry, Stay foolish! 1275

Singleton设计模式的C++实现详解

SingletonThe Singleton Pattern: ensures a class has only one instance, and provides a global point of access to it.只有一个实例的类,如下是若干考虑: 首先,要产生类实例,需要调用构造函数。为了防止用户申明或者new一个类的实例,我们可以把这个类的构造函数设置为protected

smstong的成长轨迹 2419

C++实现设计模式: Singleton 单例模式

又一次仔细读了刘未鹏写的《暗时间》,总结自己之所以在编程方面成长不理想的原因就是自己花在总结上的时间太少了,总是写过的代码和用过的模式很快就忘记了,有点过分依赖参考资料和Google. 因此,今天起陆续总结一下自己使用过的一些设计模式,不过由于C++设计模式方面的资料很少,我将坚持采用C++语言说明。 第一回:Singleton  很简单,不做说明了,有疑问请邮件联系

初心 1805

设计模式singleton的C++实现源码

1、单件类MySingleton定义#ifndef MYSINGLETON_H#define MYSINGLETON_Hclass MySingleton{public: static MySingleton* getInstance(); char* getName();private: MySingleton(char* name); ~MySingleton(); static

breeze1998的专栏 687

设计模式C++实现(1)Singleton

  以前是C程序员, 也会接触CSharp的WinForm编程, 对设计模式的CSharp实现有过一点点研究.设计模式是一种可复用的思想, 和用什么语言实现无关, 这一点是不可争议的.现在转做C++编程了, 发现在C++与CSharp或是Java的实现还是有一定的区别最近买了一本> --- 机械工业出版社 一本很不错的书, 双语版  Singleton我先假设看这段文字

visir的专栏 1004

剑指offer-Singleton单例设计模式c++实现

/* 实现Singleton单例模式c++ */ #include <iostream> #include <cstdio> #include <cstring> using namespace std; class MyString{ private: MyString(const char*str=0) { if(str...

OliverkingLi的博客 323
上一篇: 自写PNGButton类,实现透明按钮
下一篇: 构造函数初始化列表和函数内部赋值的区别
C__Allen
博客等级 码龄18年 12粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值