代码改变世界

设计模式之单例模式(c++版) - 转

2021-01-25 22:43  tangxiaosheng  阅读(85)  评论(0编辑  收藏  举报

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 。这种方法很简洁,也很完美,但是注意:

  1. gcc 4.0之后的编译器支持这种写法。
  2. C++11及以后的版本(如C++14)的多线程下,正确。
  3. 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&); // =运算符重载
};