简体   繁体   English

单例文件静态与类私有静态

[英]Singleton file static vs class private static

Is there any difference or specific advice when it comes to the following approaches for defining singletons? 以下定义单例的方法有什么区别或具体建议?

In 1, the singleton object is a class private static, but in 2, it's a file static. 在1中,单例对象是类private静态,但在2中,它是文件静态。

Note: m_initedObj1 is just there to show that class has state, and use case is to call this singleton->DoSomething() many times, without needing to init this object again. 注意:m_initedObj1只是用来表明类具有状态,用例是多次调用此singleton-> DoSomething(),而无需再次初始化此对象。

1) 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) 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 }

As JerryGoyal states in the comments , in 2) other methods in the same .cpp file can modify s_fooSingleton. 正如JerryGoyal在评论中所述 ,在2)同一.cpp文件中的其他方法可以修改s_fooSingleton。

On the other hand, they are not both thread-safe. 另一方面,它们也不都是线程安全的。 If you don't really mind the clearing (calling ClearSingleton() explicitly), just go with the Scott Meyers' version. 如果您真的不介意清除操作(显式调用ClearSingleton()),请使用Scott Meyers的版本。 Otherwise, go with the double checked locking version. 否则,请使用双重检查的锁定版本。

It's really hard to ensure the safety in case of explicitly deleting. 在显式删除的情况下,确实很难确保安全。 You always have to check whether it's deleted before you access it. 访问它之前,您始终必须检查它是否已删除。 If it's a multi-threaded executable, checking and using it must be atomic, because it can be deleted just after checking. 如果它是多线程可执行文件,则检查和使用它必须是原子的,因为可以在检查后立即将其删除。

Double checked locking could be used to create and delete the singleton, which ensures you that there is only one instance at a time. 可以使用双重检查锁定来创建和删除单例,从而确保您一次只有一个实例。 Yet, it does not ensure the object really exist, since you may accidentally delete it. 但是,它不能确保对象确实存在,因为您可能会意外删除它。

You may use smart pointers to count references and delete it if no references exist. 您可以使用智能指针对引用进行计数,如果不存在引用,则将其删除。

Or even better, see this answer https://stackoverflow.com/a/15733545/1632887 . 甚至更好,请参见以下答案https://stackoverflow.com/a/15733545/1632887

I just wouldn't delete it explicitly if I were you! 如果我是您,我只是不会明确删除它!

Maybe this will satisfy you more: 也许这会让您更加满意:

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;
    }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM