使用shared_ptr的Singleton类实现

时间:2015-10-27 21:53:09

标签: c++11

#include <iostream>
#include <memory>

using namespace std;

class Demo {
    static shared_ptr<Demo> d;
    Demo(){}
public:    
    static shared_ptr<Demo> getInstance(){
        if(!d)
        d.reset(new Demo);
        return d;
    }
    ~Demo(){
        cout << "Object Destroyed " << endl;
    }

};

//    shared_ptr<Demo> Demo::d(new Demo); // private ctor is accepted 

shared_ptr<Demo> Demo::d;

int main()
{
    shared_ptr<Demo> d(Demo::getInstance());
    cout << d.use_count() << endl;

   return 0;
}
  1. 这是使用shared_ptr
  2. 实现单例类的正确方法
  3. 请参阅上面注释的行来初始化静态shared_ptr为什么我们可以在这里创建一个对象以使用私有构造初始化shared_ptr

3 个答案:

答案 0 :(得分:8)

这不是线程安全的:调用getInstance的两个线程会导致数据竞争。一种常见的方法是使用函数范围的静态变量:

static shared_ptr<Demo> getInstance(){
  static shared_ptr<Demo> d(new Demo);
  return d;
}

当控件第一次通过其定义时,以线程安全的方式保证这样的变量只被初始化一次。

但是,目前还不清楚为什么要使用shared_ptr。你也可以这样做

static Demo& getInstance(){
  static Demo d;
  return d;
}

这是一个单例的教科书实现(嗯,其中之一)。

Re:使用私有构造函数初始化。我不确定我是否理解你混淆的本质。您是否在问为什么Demo::getInstance可以使用Demo的私有构造函数?好吧,因为它是Demo的成员,并且类的成员可以访问该类的私有成员。你问为什么Demo::getInstance可以调用shared_ptr<Demo>::reset()传递Demo*指针?好吧,因为reset()shared_ptr的公共成员函数,所以将指针作为参数。您觉得这个过程的哪个部分有争议?

答案 1 :(得分:2)

上面我的第二个问题是私有构造函数在实例化静态成员时如何调出类的一面

//    shared_ptr<Demo> Demo::d(new Demo); // private ctor is accepted 

我认为返回本地静态不会工作,请参阅下面的示例对象销毁两次

#include <iostream>

using namespace std;

class Demo {
public:
    static Demo & getInstance(){
        static Demo d;
        return d;
    }
    ~Demo(){
        cout << "Demo destroyed" << endl;
    }
};

void fun(){
    Demo l = Demo::getInstance();

}
int main()
{
    fun();
   cout << "Hello World" << endl; 
}

答案 2 :(得分:0)

1的一些评论有助于讨论。静态变量将在应用程序退出时被销毁,因此如上所述,我们现阶段无需使用智能指针。

“如果多个线程尝试同时初始化同一静态局部变量,则初始化仅发生一次(可以使用std :: call_once获得任意功能的相似行为)。

注意:此功能的常规实现使用双重检查的锁定模式的变体,从而将已经初始化的局部静态数据的运行时开销减少到单个非原子布尔比较。 (自C ++ 11起)

仅在初始化成功完成的情况下,才在程序出口处调用块范围静态变量的析构函数。 “