https://segmentfault.com/a/1190000015950693# 和 https://juejin.cn/post/6844903928497176584, 后面这个有调用实例。
摘录最简洁的方式。
实现六[c++ 11版本最简洁的跨平台方案]
实现四的方案有点麻烦,实现五的方案不能跨平台。其实c++ 11
中已经提供了std::call_once
方法来保证函数在多线程环境中只被调用一次,同样,他也需要一个once_flag
的参数。用法和pthread_once
类似,并且支持跨平台。
实际上,还有一种最为简单的方案!
在C++memory model中对static local variable,说道:The initialization of such a variable is defined to occur the first time control passes through its declaration; for multiple threads calling the function, this means there’s the potential for a race condition to define first.
局部静态变量不仅只会初始化一次,而且还是线程安全的。
class Singleton{
public:
// 注意返回的是引用。
static Singleton& getInstance(){
static Singleton m_instance; //局部静态变量
return m_instance;
}
private:
Singleton(); //私有构造函数,不允许使用者自己生成对象
Singleton(const Singleton& other);
};
这种单例被称为Meyers' Singleton
。这种方法很简洁,也很完美,但是注意:
- gcc 4.0之后的编译器支持这种写法。
- C++11及以后的版本(如C++14)的多线程下,正确。
- C++11之前不能这么写。
但是现在都18年了。。新项目一般都支持了c++11
了。
用模板包装单例
从上面已经知道了单例模式的各种实现方式。但是有没有感到一点不和谐的地方?如果我class A
需要做成单例,需要这么改造class A
,如果class B
也需要做成单例,还是需要这样改造一番,是不是有点重复劳动的感觉?利用c++
的模板语法可以避免这样的重复劳动。
template<typename T>
class Singleton
{
public:
static T& getInstance() {
static T value_; //静态局部变量
return value_;
}
private:
Singleton();
~Singleton();
Singleton(const Singleton&); //拷贝构造函数
Singleton& operator=(const Singleton&); // =运算符重载
};