【问题标题】:Why the singleton works here, although a static variable is re-initialized to NULL?为什么单例在这里工作,尽管一个静态变量被重新初始化为 NULL?
【发布时间】:2014-03-03 14:00:42
【问题描述】:

在此示例中,我希望实例每次都重新初始化为 NULL。因此,它不应该起作用,它应该每次都做新的。但是,它实际上是作为单例工作的。因此,new 只被调用一次。为什么它有效?我在这里很困惑。

class Factory_model
{
public:

    static  Factory_model*    Instance(void);

};

Factory_model*    Factory_model::Instance(void)
{
    static Factory_model* instance = NULL;

    if(instance == NULL)
    {
        qDebug()<< "Creating instance now"<<endl;
        instance = new Factory_model;

    }

    return(instance);
}

int main(int argc, char *argv[])
{

   Factory_model *ptr =  Factory_model::Instance();
   Factory_model *ptr2 =  Factory_model::Instance();
   Factory_model *ptr3 = Factory_model::Instance();
}

输出如下 - 立即创建实例

【问题讨论】:

  • 注意static Factory_model* instance = NULL;和static Factory_model* instance; instance = NULL;之间的区别。

标签: c++


【解决方案1】:

我希望实例每次都重新初始化为 NULL。

不,静态变量只初始化一次,在程序第一次到达定义时(或者更早,如果可以静态初始化的话)。

当然,你有内存泄漏,对象创建不是线程安全的;但这不是yet another essay 讨论单例反模式危险的地方。

【讨论】:

  • 我这里注入了什么内存泄漏?另外,为什么它不是线程安全的。
  • @SHREYASJOSHI:new 没有匹配的delete,因此存在内存泄漏。如果两个线程同时调用该函数,它们可能都发现变量为空,并且都创建了对象。 (可能不值得尝试修复泄漏,因为替代方案将很快导致终身问题的噩梦。如有必要,您可以通过在启动线程之前故意调用访问器来避开线程问题。或者您可以为自己节省一个放弃单例的想法会很痛苦。)
  • 泄漏的另一个定义是一个没有引用它的对象;根据这个定义,它不是泄漏。
  • @Bryan:好的;我正在使用创建但未销毁的对象的定义。但是,我们不要陷入对与问题无关的评论的语义争论中。
  • 没错,线程安全部分也取决于我将如何访问公共代码,互斥锁可以防止这种情况。所以,应该考虑做线程而不是在这里。
【解决方案2】:

行:

static Factory_model* instance = NULL;

只执行一次;这就是关键字static 在局部变量上使用时的含义。不是每次进入函数都执行初始化。

见The static keyword and its various uses in C++ 或http://www.cprogramming.com/tutorial/statickeyword.html

【讨论】:

    【解决方案3】:

    还有,看看这个:

    Singleton instance declared as static variable of GetInstance method

    ...每次涉及到 c++ 静态变量和单例,这是一个你应该知道的技术

    【讨论】:

      【解决方案4】:
      static Factory_model* instance = NULL;
      

      创建一个名为instance 的静态存储持续时间变量并将其初始化一次。您是正确的,因为每次都会初始化一个变体没有static 关键字,但static 在这里有所不同。

      它实际上与您在函数之外 声明它一样,但具有最小化范围的额外好处(可以看到 变量的什么)。在函数内部创建静态存储持续时间变量意味着只有函数可以看到/使用它(在发布指针或引用时没有任何技巧),并且它在函数调用之间保持其值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-06
        • 2017-12-07
        • 1970-01-01
        • 1970-01-01
        • 2018-08-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多