C++ 非完美Singleton

Python小白也能玩转迅投QMT量化交易?手把手教你从安装到第一个策略 本文为零基础Python用户提供了上手迅投QMT量化交易平台的完整指南。从Python 3.6环境配置、QMT客户端获取安装,到核心概念讲解,并手把手教你编写并回测一个经典的双均线交易策略,帮助初学者快速迈出量化交易的第一步。 阅读详情

非完美C++ Singleton实现[1]

Singleton模式是一种非常简单的设计模式,这种模式很常用也很容易被滥用。当你设计应用程序的时候,经常会遇到某些对象在整个程序的生命周期应该仅有一个实例的情况,比如File System,Graphic System,Logging Utility,这时候就可以用到Singleton模式。Singleton模式在GOF中描述如下:

Ensure a class only has one instance, and provide a global point of access to it.

Singleton模式的定义很简单,实现也有N多种,但是却很难找到一个称得上“完美”的。实现一个完美的Singleton比想象中要难的多,下面探索性的来实现一个非完美的。

1.典型实现
在C++中,Singleton模式的典型实现如下:

1 // Header file Singleton.h
2 class Singleton {
3 public
:
4 static Singleton& Instance() { // Unique point of access

5 if (0 == _instance)
6 _instance = new
Singleton();
7 return *
_instance;
8
}
9 void
DoSomething();
10 private
:
11 Singleton(); // Prevent clients from creating a new Singleton

12 ~Singleton(); // Prevent clients from deleting a Singleton
13 Singleton(const Singleton&); // Prevent clients from copying a Singleton
14 Singleton& operator=(const Singleton& );
15 private
:
16 static Singleton *_instance; // The one and only instance

17 };
18

19 // Implementation file Singleton.cpp
20 Singleton* Singleton::_instance = 0;


通过将Singleton的构造函数设为private可以禁止客户代码直接创建Singleton对象,除此之外,Singleton的copy constructor和copy assignment operator都为private且仅有声明没有实现,禁止了客户代码拷贝Singleton对象。唯一可以创建Singleton对象的是Singleton自己的静态成员函数Instance,这样就在编译器保证了Singleton实例的唯一性。上面这些是在C++中实现Singleton模式最基本的要点。

Instance方法保证只有在第一次调用时才会生成Singleton对象,以后的调用只是简单返回唯一的已存在的实例。Instance方法实际上实现的是懒惰初始化(lazy initialize),如果程序中根本没有用到Singleton对象,也就根本不会产生Singleton的实例,这在Singleton对象很少使用且创建Singleton对象开销比较大的情况下特别有用。

客户代码现在可以这样使用Singleton:

1 Singleton &s = Singleton::Instance();
2 s.DoSomething();


还需要说明的是Singleton的析构函数,析构函数也为private可以禁止客户写出如下代码。如果某个客户写出了如下代码,随后的对Singleton的访问就会导致为定义行为,因为Singleton对象已经不存在。

1 Singleton *p = & Singleton::Instance();
2 delete p;


2.引入smart pointer
上面的实现算是一个好的实现吗?当然不是,或许连一个正确的实现都算不上。如果你想凑合,当然没问题,上面的代码大多数情况下可以工作的很好。也许你已经注意到了一些问题,比如说在上面的代码中只有new没有delete。是的,你说会发生memory leak对吧,其实memory leak都不是主要的问题,所有的现代操作系统在进程结束的时候都会对内存很好的进行回收。比memory leak更值得让人担忧的是resource leak,如果Singleton在构造函数中请求了某些资源:网络连接,文件句柄,数据库连接等。这些资源将得不到释放。

唯一修正resource leak的方法就是在程序结束的时候delete _instance。当然了,用smart pointer再好不过,在这里用auto_ptr就可以满足需要了(如果你还不知道smart_ptr是什么,花点时间熟悉C++标准库吧),修改后的代码如下:

1 // Header file Singleton.h
2 class Singleton {
3 public
:
4 static Singleton& Instance() { // Unique point of access

5 if (0 == _instance.get())
6 _instance.reset(new
Singleton());
7 return *
(_instance.get());
8
}
9 void
DoSomething(){}
10 private
:
11 Singleton(){} // Prevent clients from creating a new Singleton

12 ~Singleton(){} // Prevent clients from deleting a Singleton
13 Singleton(const Singleton&); // Prevent clients from copying a Singleton
14 Singleton& operator=(const Singleton& );
15 private
:
16 friend auto_ptr<Singleton>
;
17 static auto_ptr<Singleton> _instance; // The one and only instance

18 };
19

20 // Implementation file Singleton.cpp
21 auto_ptr<Singleton> Singleton::_instance;


3.用atexit替换smart pointer
C++并没有规定不同编译单元(translation unit,简单说就是一个可编译的cpp文件)中static对象的初始化顺序。如果一个程序中有多个Singleton对象,那么这些Singleton对象的析构顺序也将是任意的。很显然,当多个Singleton对象有依赖关系时,smart pointer根本无法保证Singleton的析构顺序。

msdn中对atexit描述如下:

The atexit function is passed the address of a function (func) to be called when the program terminates normally. Successive calls to atexit create a register of functions that are executed in last-in, first-out (LIFO) order. The functions passed to atexit cannot take parameters. atexit use the heap to hold the register of functions. Thus, the number of functions that can be registered is limited only by heap memory.

需要说明的是atexit并不比smart pointer好多少,LIFO的保证对于有复杂依赖关系的多个Singleton依然束手无力,但是用atexit替换smart pointer却是必须的,它是设计完美Singleton的基础。


#如果你疑惑atexit为什么还是不行,请考虑下面的情况:
NOTE:下面的情况在Modern C++ Design中叫做KDL(Keyboard,Display,Log)problem。

某个程序中使用了如下3个Singleton:Keyboard,Display,Log。Keyboard和Display分别对应于计算机的键盘和显示器,Log用来记录错误信息。假设当Keyboard和Display的构造函数和析构函数出现错误时会调用Log记录错误信息,并且构造和析构导致的任何错误都会终止程序。

在程序启动时,如果Keyboard构造成功,Display构造失败,很显然在Display的构造函数中将会构造Log而且失败信息会被Log记录,根据假设这时候程序准备退出,atexit注册的函数将会按LIFO的顺序被调用。因为Keyboard先于Log构造,所以Log先于Keyboard析构,但是当由于某种原因Keyboard在析构时失败,想要调用Log记录错误信息时,Log早已被销毁,则Log::Instance()将会导致未定义行为。

#atexit的严重问题:
从上面的例子可以看出,atexit和smart pointer相比仅仅是有LIFO的保证而已,这样的保证貌似也不怎么有效,因为atexit跟smart pointer一样也无法解决KDL probleam。

atexit由于LIFO带来了另外的问题,看下面的代码:

1 #include <cstdlib>
2 void Bar() {
3
...
4
}
5 void
Foo() {
6
std::atexit(Bar);
7
}
8 int
main() {
9
std::atexit(Foo);
10 return 0
;
11 }

上面的小段代码用atexit注册了Foo,Foo调用了std::atexit(Bar)。当程序退出时,根据atexit的LIFO保证,Bar在Foo之后注册,因此Bar应该在Foo之前调用,但是当Bar注册的时候Foo已经调用了,Bar根本就没有机会能够在Foo之前调用。这明显自相矛盾对吧,没办法,C++标准好像忽视了这一点,因此如果类似代码被调用,肯定不会有什么好的结果,好一点是resource leak,差一点估计程序就崩溃了!!!

atexit的这个问题跟Singleton有关系吗?当然有,如果在一个Singleton的析构函数中调用atexit就会出现上述问题。即在KDL problem中,如果Keyboard和Display都构造成功,当Keyboard或Display任意一个析构失败时,Keyboard或Display在析构函数中会构造Log,Log的构造函数会间接调用atexit。oops!!!,可怕的未定义行为。

看到这里你一定对atexit相当失望,貌似它带来的好处多于坏处。但是请你相信,如果适当设计,atexit在后面的Singleton改造中会起到很重要的作用。

用atexit后的代码:

1 // Header file Singleton.h
2 class Singleton {
3 public
:
4 static Singleton& Instance() { // Unique point of access

5 if (0 == _instance) {
6 _instance = new
Singleton();
7 atexit(Destroy); // Register Destroy function

8 }
9 return *
_instance;
10
}
11 void
DoSomething(){}
12 private
:
13 static void Destroy() { // Destroy the only instance

14 if ( _instance != 0 ) {
15
delete _instance;
16 _instance = 0
;
17
}
18
}
19 Singleton(){} // Prevent clients from creating a new Singleton

20 ~Singleton(){} // Prevent clients from deleting a Singleton
21 Singleton(const Singleton&); // Prevent clients from copying a Singleton
22 Singleton& operator=(const Singleton& );
23 private
:
24 static Singleton *_instance; // The one and only instance

25 };
26

27 // Implementation file Singleton.cpp
28 Singleton* Singleton::_instance = 0;

你有没有仔细考虑过Destroy中的_instance = 0;这一行代码,上述代码实际上实现的是 不死鸟模式(The Phoenix Singleton),所谓不死鸟,就跟一辉一样可以死而复生。上面的代码可以解决本文最早提出的 KDL problem,即如果 Keyboard析构失败,虽然 Log已经析构,但是由于Destroy中的_instance = 0;这一行代码,Log::Instance()将会创建一个新的 Log对象,程序将会表现良好。当然了, Phoenix Singleton仅能用于无状态的Singleton,如果 Log需要保存某些状态, Phoenix Singleton也不会带来任何好处。你当然可以用某些方法维持 Phoenix Singleton的状态,但是在做之前先想想看是否值得,维持状态可能会使Singleton变得特别复杂。

上面的 Phoenix Singleton已经可以满足大部分需要,如果你的Singleton没有涉及到多线程,多个Singleton之间也没有依赖关系,你大可以放心使用。但是如果你用到多线程,或者你的Singleton关系如 KDL般复杂,或者你觉得对每一个Singleton都敲同样的代码让你厌烦。在后面几篇会有一个 多线程安全的,能够 解决多个Singleton依赖关系的, 基于模板的Singleton实现。
4.解决多线程问题
上一篇实现的Singleton只能在单线程环境中使用,在多线程环境中会出现很多问题,看Instance()实现代码:
1 static Singleton& Instance() {
2 if (0 == _instance) { //1

3 _instance = new Singleton(); //2
4 atexit(Destroy);
5
}
6 return *_instance; //3

7 }
考虑如下情况:线程一调用Instance(),进入//1,0 == _instance 返回true,线程一于是进入//2。这时候线程一被挂起,线程二开始执行,线程二调用Instance(),进入//1,发现0 == _instance 仍然返回true,线程二于是也进入//2,线程二继续执行到//3直到返回。这时候线程一被唤醒,继续从//2开始执行,这将会覆盖线程二创建的_instance,线程一继续执行到//3直到返回...

解决方法很简单,引入相关同步对象(synchronization object)就行了,例如在win32平台下可以如下实现:
synobj.h
1 #ifndef SYNOBJ_H
2
#define SYNOBJ_H
3

4 #include <windows.h>
5
6 #define CLASS_UNCOPYABLE(classname) \
7 private
: \
8 classname(const classname&
); \
9 classname& operator=(const classname&
);
10

11 class Mutex {
12
CLASS_UNCOPYABLE(Mutex)
13 public
:
14 Mutex() :_cs() { InitializeCriticalSection(&
_cs); }
15 ~Mutex() { DeleteCriticalSection(&
_cs); }
16 void lock() { EnterCriticalSection(&
_cs); }
17 void unlock() { LeaveCriticalSection(&
_cs); }
18 private
:
19
CRITICAL_SECTION _cs;
20
};
21

22 class Lock {
23
CLASS_UNCOPYABLE(Lock)
24 public
:
25 explicit Lock(Mutex&
cs) :_cs(cs) { _cs.lock(); }
26 ~
Lock() { _cs.unlock(); }
27 private
:
28 Mutex&
_cs;
29
};
30

31 #endif/*SYNOBJ_H*/

有了同步对象很容易就能够写出如下代码:
singleton.h
1 #ifndef SINGLETON_H
2
#define SINGLETON_H
3

4 #include "synobj.h"
5
6 class Singleton {
7 public
:
8 static Singleton& Instance() { // Unique point of access

9 Lock lock(_mutex);
10 if (0 ==
_instance) {
11 _instance = new
Singleton();
12 atexit(Destroy); // Register Destroy function

13 }
14 return *
_instance;
15
}
16 void
DoSomething(){}
17 private
:
18 static void Destroy() { // Destroy the only instance

19 if ( _instance != 0 ) {
20
delete _instance;
21 _instance = 0
;
22
}
23
}
24 Singleton(){} // Prevent clients from creating a new Singleton

25 ~Singleton(){} // Prevent clients from deleting a Singleton
26 Singleton(const Singleton&); // Prevent clients from copying a Singleton
27 Singleton& operator=(const Singleton& );
28 private
:
29 static
Mutex _mutex;
30 static Singleton *_instance; // The one and only instance

31 };
32

33 #endif/*SINGLETON_H*/

singleton.cpp
1 #include "singleton.h"
2
3 Mutex Singleton::_mutex;
4 Singleton* Singleton::_instance = 0;
现在的Singleton虽然多线程安全,性能却受到了影响。从Instance()中可以看到,实际上仅仅当0 == _instance为true时才需要Lock。你很容易就写出如下代码:
1 static Singleton& Instance() {
2 if (0 ==
_instance) {
3
Lock lock(_mutex);
4 _instance = new
Singleton();
5
atexit(Destroy);
6
}
7 return *
_instance;
8 }
但是这样还是会产生竞争条件(race condition),一种广为人知的做法是使用所谓的Double-Checked Locking:
1 static Singleton& Instance() {
2 if (0 ==
_instance) {
3
Lock lock(_mutex);
4 if (0 ==
_instance) {
5 _instance = new
Singleton();
6
atexit(Destroy);
7
}
8
}
9 return *
_instance;
10 }
Double-Checked Locking机制看起来像是一个完美的解决方案,但是在某些条件下仍然不行。简单的说,编译器为了效率可能会重排指令的执行顺序( compiler-based reorderings)。看这一行代码:

_instance = new Singleton();

在编译器未优化的情况下顺序如下:
1.new operator分配适当的内存;
2.在分配的内存上构造Singleton对象;
3.内存地址赋值给_instance。


但是当编译器优化后执行顺序可能如下:
1.new operator分配适当的内存;
2.内存地址赋值给_instance;
3.在分配的内存上构造Singleton对象。


当编译器优化后,如果线程一执行到2后被挂起。线程二开始执行并发现0 == _instance为false,于是直接return,而这时Singleton对象可能还未构造完成,后果...

上面说的还只是单处理器的情况,在多处理器(multiprocessors)的情况下,超线程技术必然会混合执行指令,指令的执行顺序更无法保障。关于Double-Checked Locking的更详细的文章,请看:
The "Double-Checked Locking is Broken" Declaration

5.使用volatile关键字
为了说明问题,请先考虑如下代码:
1 class MyThread : public Thread {
2 public
:
3 virtual void
run() {
4 while (!
_stopped) {
5 //do something

6 }
7
}
8 void
stop() {
9 _stopped = true
;
10
}
11 private
:
12
bool _stopped;
13
};
14

15 ...
16
17 MyThread thread;
18 thread.start();
上面用thread.start()开启了一个线程,该线程在while循环中检测bool标记_stopped,看是否该继续执行。如果想要结束这个线程,调用thread.stop()应该没问题。但是需要注意的是编译器很有可能对_stopped的存取进行优化。如果编译器发现_stopped被频繁存取(_stopped在while循环中),编译器可能会考虑将_stopped缓存到寄存器中,以后_stopped将会直接从寄存器存取。这时候如果某个线程调用了thread.stop(),对_stopped的修改将不会反映到寄存器中,thread将会永远循环下去...

为了防止编译器优化,用volatile关键字就OK了,volatile跟const的用法几乎一样,能用const的地方也都能用volatile。对Singleton来说,修改如下两处即可:
1 //singleton.h中
2 static Singleton * _instance;
3 //改为

4 static Singleton * volatile _instance;
5

6 //singleton.cpp中
7 Singleton* Singleton::_instance = 0 ;
8 //改为

9 Singleton* volatile Singleton::_instance = 0;


6.将Singleton泛化为模板
singleton.h
1 #ifndef SINGLETON_H
2
#define SINGLETON_H
3

4 #include "synobj.h"
5
6 template<class T>
7 class Singleton {
8
CLASS_UNCOPYABLE(Singleton)
9 public
:
10 static T& Instance() { // Unique point of access

11 if (0 == _instance) {
12
Lock lock(_mutex);
13 if (0 ==
_instance) {
14 _instance = new
T();
15
atexit(Destroy);
16
}
17
}
18 return *
_instance;
19
}
20 protected
:
21
Singleton(){}
22 ~
Singleton(){}
23 private
:
24 static void Destroy() { // Destroy the only instance

25 if ( _instance != 0 ) {
26
delete _instance;
27 _instance = 0
;
28
}
29
}
30 static
Mutex _mutex;
31 static T * volatile _instance; // The one and only instance

32 };
33

34 template<class T>
35 Mutex Singleton<T> ::_mutex;
36

37 template<class T>
38 T * volatile Singleton<T>::_instance = 0 ;
39

40 #endif/*SINGLETON_H*/

测试代码:
test.cpp
1 #include "singleton.h"
2
3 class A : public Singleton<A> {
4 friend class Singleton<A>
;
5 protected
:
6
A(){}
7 ~
A(){}
8 public
:
9 void
DoSomething(){}
10
};
11

12 int main() {
13

14 A &a = A::Instance();
15
a.DoSomething();
16

17 return 0 ;
18 }


7.Singleton的析构问题
到此Singleton已经算比较完善了,但是依然算不上完美,因为到现在只是解决了多线程问题,加入了模板支持,对于KDL problem(The Dead Reference Problem)依然没法解决,可以说在实现Singleton模式时,最大的问题就是多个有依赖关系的Singleton的析构顺序。虽然Modern C++ Design中给出了解决方案,但是Loki的实现太过复杂,在此就不详细说明了,有兴趣的可以看看Modern C++ Design,当然了,Loki库中用策略模式实现的Singleton也很不错!

宇树机器人G1二次开发:语音对话、打断与激活功能实现指南 宇树机器人G1是一款功能强大的四足机器人,其开放的SDK和API为开发者提供了广阔的二次开发空间。其中,语音交互是提升机器人智能化水平和用户体验的关键功能。本文将详细介绍如何在宇树机器人G1上进行二次开发,实现。语音打断允许用户在机器人说话时随时中断并输入新指令,这是提升交互自然度的关键功能。三大核心功能,帮助你构建更自然、更智能的人机交互系统。语音识别是将用户的语音输入转换为文本的过程。识别文本后,需要理解用户意图并生成回复。将文本回复转换为语音输出。 阅读详情

相关推荐

若依集成mybatisplus、兼容旧分页【亲测有效】

service类继承ServiceImpl类 实现 你的Service接口。hutool工具包和lombok工具包如果不需要的话可以自行删除并修改后面的类里面的代码。自带的pagehelper用的1.4.6里面的jsqlparser用的4.5.0。mybatis-plus用的3.4.2里面的jsqlparser用的4.0.0。jsqlparser包,不剔除是这样的,有个冲突,我用的前端写的请求,返回的格式和原来的一样,已兼容。你的Entity类上面需要增加表的名字。

lh155136的博客 3566

Singleton模式

<br />Singleton模式是一种非常简单的设计模式,这种模式很常用也很容易被滥用。当你设计应用程序的时候,经常会遇到某些对象在整个程序的生命周期应该仅有一个实例的情况,比如File System,Graphic System,Logging Utility,这时候就可以用到Singleton模式。Singleton模式在GOF中描述如下:<br /><br />        Ensure a class only has one instance, and provide a global poi

lfb555的专栏 1396

FPGA实战:手把手教你用Verilog实现Modbus CRC16校验(附完整代码)

本文详细介绍了在FPGA中实现Modbus RTU协议CRC16校验模块的完整实战方案。针对硬件设计中的时序、资源与性能挑战,文章从算法原理出发,提供了清晰的Verilog模块接口、状态机设计、查表ROM实现及优化策略,并附带了完整的可综合代码与测试平台,帮助工程师高效构建稳定可靠的工业通信系统。

weixin_29164185的博客 431

设计模式,单例模式,singleton,Instance,c++实现,一个国家一个国王

单例模式singleton 定义: 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 翻译: 有一个类,在程序进程中只有一个,程序开始时自动初始化自己的实例,程序结束后被释放,程序员不用也无法手动new或delete那样一个类的对象,这个类的唯一的对象会在整个进程中发挥作用,可随时被进程中的任何函数访问。 类图摘自设计模式之禅 特点: 单例类只有一个实例化的对象,这个对象的获取往往通过在类中设置Instance()/GetInstance()等方法获取,这是一般单例模式的默认命名,而只要

ganfanren00001的博客 954

ICT调试技巧:从基础到实战的全面指南

本文提供了一份全面的ICT调试技巧指南,涵盖从基础认知到实战应用的全过程。详细解析了ICT设备硬件结构、程序文件构成,并重点讲解了调试界面的核心参数与高效快捷键。通过跳线、电阻、电容及二极管等常见元器件的实战调试案例,分享了参数设置要点与典型问题解决方案,帮助工程师快速掌握ICT调试核心技能,提升测试效率与准确性。

weixin_29202213的博客 341

学术报告系列(二) - 智能自主作业机器人感知与控制技术及发展趋势

收集整理于2022年模式识别高峰论坛湖南大学王耀南院士报告(报名题目:智能自主作业机器人感知与控制技术及发展趋势)

Make something people want. 4696

Java设计模式

设计模式一.单例模式饿汉式懒汉式双重检查(推荐) 一.单例模式 定义 涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象 注意 单例类只能有一个实例 单例类必须自己创建自己的唯一实例 单例类必须给所有其他对象提供这一实例 饿汉式 (静态变量)内存浪费 public class SingletonTes...

weixin_43838890的博客 398

使用 Simulink + Simscape Electrical 搭建一个三相PWM整流器模型

本文详细介绍了使用Simulink搭建三相PWM整流器模型的方法,重点讲解了SVPWM调制策略的实现过程。内容包括系统结构设计、主电路搭建、SVPWM算法实现、双闭环控制器设计以及仿真分析。通过MATLAB Function Block实现SVPWM核心算法,并给出优化建议,如死区补偿、开关频率优化等。该教程为电力电子领域工程师提供了实用的建模与仿真方法,可用于新能源并网、电机驱动等应用场景的研发与优化。

amy_mhd的博客 195

utilities(C++)——单例(Singleton)

通过类名获得类实例指针 禁止拷贝 将构造函数声明为私有的

1528

第10章《VTK自定义部件Widget》

是用于交互式操作 3D 场景的组件,例如移动对象、调整尺寸、创建标注等。VTK 提供了一些内置的 Widget,如。,用户可以点击鼠标,在 3D 场景中放置一个点。负责绘制一个点,并控制其颜色、大小等。,可用于 3D 标注、对象拾取等应用!等,但在某些应用中,我们需要。这样,我们就创建了一个。

yumeiguo的博客 523

Openclaw 附录B 常用Skills清单

核心作用支持URL、网页、PDF、图片、音频和YouTube视频的摘要与字幕提取,由OpenClaw创始人@steipete开发的官方内置Skill。安装⚠️说明:原推荐的summarize未在ClawHub验证到,YouTube字幕提取功能已内置于summarize中。使用场景“提取这个2小时Next.js教程视频的核心代码逻辑,按章节整理成学习笔记”推荐指数:⭐⭐⭐⭐。

Maynor的博客 856

单例模式(单例设计模式)详解

在有些系统中,为了节省内存资源、保证数据内容的一致性,对某些类要求只能创建一个实例,这就是所谓的单例模式。 单例模式的定义与特点 单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。 在计算机系统中,还有 Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程

GJ_007的博客 4万+

【BUG已解决】ImportError: cannot import name ‘OpenAI‘ from ‘openai‘ 解决方案

的核心是版本不匹配用确认当前版本如果是 0.x 版本 →升级到 1.x升级后代码语法要同步改为团队协作项目务必在中锁定版本号,避免"我这能跑,你那不能跑"的问题对接国产模型时,只需替换base_url参数,SDK 调用方式完全一致。

一键难忘的博客 1万+

非完美C++ Singleton实现

非完美C++ Singleton实现[1] Singleton模式是一种非常简单的设计模式,这种模式很常用也很容易被滥用。当你设计应用程序的时候,经常会遇到某些对象在整个程序的生命周期应该仅有一个实例的情况,比如File System,Graphic System,Logging Utility,这时候就可以用到Singleton模式。Singleton模式在GOF中描述如下:       

kikikind的专栏 2254

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

非完美C++ Singleton实现[2]

非完美C++ Singleton实现[2] 4.解决多线程问题上一篇实现的Singleton只能在单线程环境中使用,在多线程环境中会出现很多问题,看Instance()实现代码:1 static Singleton& Instance() {2     if (0 == _instance) { //13         _instance = new Singleton(); //24 

benny5609的专栏 1232

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

非完美C++ Singleton实现[1]

非完美C++ Singleton实现[1] Singleton模式是一种非常简单的设计模式,这种模式很常用也很容易被滥用。当你设计应用程序的时候,经常会遇到某些对象在整个程序的生命周期应该仅有一个实例的情况,比如File System,Graphic System,Logging Utility,这时候就可以用到Singleton模式。Singleton模式在GOF中描述如下:       

benny5609的专栏 836

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

非完美C++ Singleton实现[转载]

Singleton模式是一种非常简单的设计模式,这种模式很常用也很容易被滥用。当你设计应用程序的时候,经常会遇到某些对象在整个程序的生命周期应该仅有一个实例的情况,比如File System,Graphic System,Logging Utility,这时候就可以用到Singleton模式。Singleton模式在GOF中描述如下: Ens...

weixin_34109408的博客 110

volatile语义及线程安全singleton模式探讨

1.引言 详尽的讨论了volatile语义以及如何用C++实现线程安全的Singleton模式。 主要参考Scott Meyers and Andrei Alexandrescu写的“C++ and the Perils of Double-Checked Locking”,这是

小宝的专栏 851

C++完美实现Singleton模式

Singleton模式是常用的设计模式之一,但是要实现一个真正实用的设计模式却也不是件容易的事情。 1. 标准的实现 class Singleton { public: static Singleton * Instance() { if( 0== _instance) { _instance = new Singleton; }

xu的blog 1602
上一篇: [QT] error LNK2001: 无法解析的外部符号 Qt的moc机制
下一篇: QT小技巧
wpc320
博客等级 码龄20年 46粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值