微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 陷阱:静态堆栈变量Singleton类

我已经有一些使用指针的单例类:

class Logger
{
public:

    static Logger* Instance()
    {
        if (!m_pInstance) m_pInstance = new Logger;
        return m_pInstance;
    }
private:
    Logger();
    Logger(Logger const&);
    Logger& operator=(Logger const&);
    static Logger* m_pInstance;
};

但是,有一种更简单的方法,使用引用:

class Logger
{
public:
    static Logger& Instance()
    {
        static Logger theLogger;
        return theLogger;
    }
private:
    Logger();
    Logger(Logger const&);
    Logger& operator=(Logger const&);
    ~Logger();
};

阅读文章C++ Singleton design pattern,它警告第二种方式:

[Potential Pitfall]: This form of the singleton can present a problem
because of the life expectancy of the object. If one singleton is
instantiated within another,one must be keenly aware of the
destructor call sequence.

但我无法理解,有人能告诉我一个不好的用法,我应该避免它吗?

解决方法

两种选择确实存在问题.

典型的单身人士

class Logger
{
public:

    static Logger* Instance()
    {
        if (!m_pInstance) m_pInstance = new Logger;
        return m_pInstance;
    }
private:
    Logger();
    Logger(Logger const&);
    Logger& operator=(Logger const&);
    static Logger* m_pInstance;
};

代码不是线程安全的,因此对新Logger的调用可能会多次发生(在不同的线程中).它还会泄漏Logger实例(因为它永远不会被删除),如果应该执行析构函数,这可能是一个问题.

梅耶的辛格尔顿

class Logger
{
public:
    static Logger& Instance()
    {
        static Logger theLogger;
        return theLogger;
    }
private:
    Logger();
    Logger(Logger const&);
    Logger& operator=(Logger const&);
    ~Logger();
};

Meyer’s Singleton的问题确实是由于对象的破坏.从main返回后,所有全局变量的析构函数将按照构造这些全局变量的相反顺序运行1.这就好像这些全局变量是在堆栈上构造的.

如果在Logger之前构造了一个对象,并试图在它自己的析构函数中使用它;然后它将使用已经被破坏的对象,导致未定义的行为.

1更准确地说,它们的构造函数以相反的顺序完成.

最简单的选择是重新审视典型单身人士:

class Logger {
public:
    static Logger& Instance() {
        static Logger* L = new Logger;
        return *L;
    }
private:
    ...
};

这现在是线程安全的,但仍然泄漏.但实际上这里需要泄漏,因为它可以保证这个对象比任何其他析构函数都被调用的时间更长.警告:如果你曾经在析构函数中做过一些事情,它将永远不会运行.

还有其他的变化,例如Alexandrescu的凤凰Singleton从它的灰烬中回来,如果它在它死后需要它;但是,在破坏期间获得线程安全性和安全性很难实现.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐