更好地理解C ++中的Singleton类

时间:2014-05-19 09:48:21

标签: c++ reference singleton

我编写了一个非常简单的程序来实现一个通用的Singleton类,如下所示:

namespace core
{
    template <typename T>
    class Singleton
    {
        protected:
            Singleton(void);
            Singleton(Singleton const &other);
            virtual ~Singleton(void);
        public:
            Singleton &operator=(Singleton const &other);
            static T *GetSingletonPtr(void);
            static T &GetSingleton(void);
            static void DestroySingleton(void);
        private:
            static T *m_pInstance;
            static T m_Instance;
    };

    //Globals initialization

    template <typename T>
    T *Singleton<T>::m_pInstance = NULL;

    template <typename T>
    T Singleton<T>::m_Instance = T();

    //Initialization

    template <typename T>
    Singleton<T>::Singleton(void)
    {

    }

    template <typename T>
    Singleton<T>::Singleton(Singleton<T> const &other)
    {
        *this = other;
    }

    //Destruction

    template <typename T>
    Singleton<T>::~Singleton(void)
    {

    }

    //Surcharges

    template <typename T>
    Singleton<T> &Singleton<T>::operator=(Singleton<T> const &other)
    {
        if (&other != this)
        {
            m_pInstance = other.m_pInstance;
            m_Instance = other.m_Instance;
        }
        return (*this);
    }

    //Others

    template <typename T>
    T *Singleton<T>::GetSingletonPtr(void)
    {
        if (m_pInstance == NULL)
            m_pInstance = new T();
        return (m_pInstance);
    }

    template <typename T>
    T &Singleton<T>::GetSingleton(void)
    {
        return (m_Instance);
    }

    template <typename T>
    void Singleton<T>::DestroySingleton(void)
    {
        if (m_pInstance != NULL)
        {
            delete (m_pInstance);
            m_pInstance = NULL;
        }
    }
}

然后,我在单例类'TestSingleton'的构造函数中使用日志'constructor:toto'编写了以下代码。

#include <iostream>
#include <Singleton.hpp>

class TestSingleton : public core::Singleton<TestSingleton>
{
        friend class core::Singleton<TestSingleton>;
    private:
        TestSingleton(void)
        {
            std::cout << "constructor:toto" << std::endl;
        }
};

class HandleSingleton
{
    public:
        void Handle()
        {
            TestSingleton &test = TestSingleton::GetSingleton();
        }
};

int main(void)
{
    getchar();
    return (0);
}

输出如下:

$> constructor:toto

我不明白为什么即使初始化此引用的方法(此处为方法'Handle')未被调用,也会初始化带引用的变量?

提前感谢您的帮助!

3 个答案:

答案 0 :(得分:3)

您的Singleton类使用T的静态实例。在调用main之前,将在程序启动期间初始化此实例。

粘贴中的以下代码初始化实例:

//Globals initialization

// […]

template <typename T>
T Singleton<T>::m_Instance = T();

答案 1 :(得分:0)

您的程序调用{​​{1}}实例的静态初始化和C ++标准版n3337 § 3.6.2 / 2说:

  

具有静态存储持续时间(3.7.1)或线程存储的变量   持续时间(3.7.2)应在任何其他之前进行零初始化(8.5)   初始化发生。

     

(...)

     

静态初始化应在任何动态初始化之前执行   发生(...)

答案 2 :(得分:0)

Normaly在实现Singleton类时使用成语“Construct On First Use”。

这个成语纠正了静态对象构造顺序上的一些问题(你可以搜索静态初始化顺序fiasco)。

将静态声明放在getObject方法上。然后在第一次调用此方法后调用构造函数。

Singleton的构造函数必须是私有的。

之后,根据定义,Singleton不可复制。你必须私有复制构造函数和operator =。