【问题标题】:Singleton file static vs class private static单例文件静态与类私有静态
【发布时间】:2017-04-06 05:26:55
【问题描述】:

以下定义单例的方法有什么不同或具体建议吗?

在 1 中,单例对象是类私有静态,但在 2 中,它是文件静态。

注意:m_initedObj1 只是用来表明类有状态,用例是多次调用这个singleton->DoSomething(),不需要再次初始化这个对象。

1)

// header file
class Foo {
private:
    static Foo* s_fooSingleton;
    Foo();
    Obj1 m_initedObj1;

public:
    static Foo* Singleton();
    static void ClearSingleton();
    Bar DoSomething(...);
};

// cpp file
Foo* Foo::s_fooSingleton = nullptr;
Foo::Foo() { m_initedObj1 = InitObj1Somewhere(); }

/*static*/ Foo* Foo::Singleton()
{
    if(!Foo::s_fooSingleton)
        Foo::s_fooSingleton = new Foo();
    return Foo::s_fooSingleton;
}

/*static*/ void Foo::ClearSingleton()
{
    if(Foo::s_fooSingleton)
        delete Foo::s_fooSingleton;
    Foo::s_fooSingleton = nullptr;
}

Bar Foo::DoSomething(...) { // do something }

2)

// header file
class Foo {
private:
    Foo();
    Obj1 m_initedObj1;

public:
    static Foo* Singleton();
    static void ClearSingleton();
    Bar DoSomething(...);
};

// cpp file
static Foo* s_fooSingleton = nullptr;

Foo::Foo() { m_initedObj1 = InitObj1Somewhere(); }

/*static*/ Foo* Foo::Singleton()
{
    if(!s_fooSingleton)
        s_fooSingleton = new Foo();
    return s_fooSingleton;
}

/*static*/ void Foo::ClearSingleton()
{
    if(s_fooSingleton)
        delete s_fooSingleton;
    s_fooSingleton = nullptr;
} 

Bar Foo::DoSomething(...) { // do something }

【问题讨论】:

  • in 2) 其他类方法可以修改s_fooSingleton
  • 使用 Scott Meyer 的单例。
  • 或者不要使用单例 ;-)
  • @JerryGoyal 是的,但是假设这个文件只有这个类,即使有,也不是什么大问题。
  • @GuillaumeRacicot,是的,我知道从 C++11 开始是线程安全的。但是对于上述情况,有什么区别吗?

标签: c++


【解决方案1】:

JerryGoyal states in the comments,在2)同一个.cpp文件中的其他方法可以修改s_fooSingleton。

另一方面,它们都不是线程安全的。如果您不介意清除(显式调用 ClearSingleton()),请使用 Scott Meyers' 版本。 否则,使用double checked locking 版本。

在显式删除的情况下,确实很难保证安全。在访问它之前,您始终必须检查它是否已被删除。如果它是一个多线程的可执行文件,检查和使用它必须是原子的,因为它可以在检查后立即删除。

双重检查锁定可用于创建和删除单例,这可确保您一次只有一个实例。然而,它并不能确保对象确实存在,因为您可能会不小心删除它。

您可以使用智能指针来计算引用并在不存在引用时将其删除。

或者更好,请参阅此答案https://stackoverflow.com/a/15733545/1632887

如果我是你,我只是不会明确删除它!

【讨论】:

  • “如果你不介意清理”是什么意思?这个单例不会自己销毁吗?
  • 我的意思是 ClearSingleton() 函数。它最终会被破坏,但我认为您想显式调用 ClearSingleton() 函数,这使得它更加困难。
  • 不,没关系。我可以删除该函数及其调用。谢谢!
  • 只是好奇...如果需要,我将如何按需销毁它?
  • 我尝试调用 Foo::Singleton().~Foo(),它确实调用了析构函数,但之后,如果我调用 Singleton(),相同的对象存在(并且有效),没有再次调用构造函数(在函数中添加了一些打印来跟踪这一点)。
【解决方案2】:

也许这会让你更满意:

class MyClass1 {
private:
    MyClass1(){}    
public:
    MyClass1& Instance() {
        static MyClass1 theSingleInstance;
        return theSingleInstance;
    }    
};

class MyClass2 {
private:
    MyClass2() {}    
public:
    MyClass2* Instance() {
        static MyClass2* theSingleInstance = new MyClass2;
        return theSingleInstance;
    }
};

class MyClass3 {
private:
    MyClass3() {}    
public:
    MyClass3* Instance() {
        static MyClass3 theSingleInstance;
        return &theSingleInstance;
    }
};

【讨论】:

  • 公共实例函数应该是静态的,不是吗?
猜你喜欢
  • 2012-11-26
  • 2012-07-14
  • 2013-08-19
  • 1970-01-01
  • 1970-01-01
  • 2010-10-17
  • 2012-12-15
  • 2011-02-23
相关资源
最近更新 更多