更好地理解c++中的单例类

Better understanding of Singleton class in C++

本文关键字:单例类 c++ 更好      更新时间:2023-10-16

我编写了一个非常简单的程序,实现了一个泛型单例类,如下所示:

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')没有被调用?

提前感谢您的帮助!

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

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

//Globals initialization
// […]
template <typename T>
T Singleton<T>::m_Instance = T();

程序调用T实例的静态初始化,c++标准n3337 § 3.6.2/2规定:

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

(…)

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

在实现单例类时,通常使用"首次使用时构造"这一习惯用法。

这个习惯用法纠正了静态对象构造顺序上的一些问题(您可以搜索静态初始化顺序惨败)。

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

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

之后,根据定义,Singleton是不可复制的。必须将复制构造函数和操作符=设为私有