c++模板单例静态指针初始化头文件



这个头文件中的实现有什么问题?

template <typename T>
class Singleton
{
public:
    static T* getInstance() 
    {
        if (m_instance == NULL) 
        {
            m_instance = new T();
        }
        return m_instance;
    }
private:
    static T* m_instance;
};

我这样使用它:

typedef Singleton<MyClass> MyClassSingleton;

我得到链接错误:

error LNK2001: unresolved external symbol "private: static class MyClass * Singleton<class MyClass>::m_instance" (?m_instance@?$Singleton@VMyClass@@@@0PAVMyClass@@A)

添加

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

它可以工作,但是我担心两件事:

    静态成员应该在.cpp文件中定义,以便在所有编译单元中只有一个实例,即使您将头文件包含在10个源文件中。
  1. 指针被初始化为NULL标准,为什么我需要显式初始化?

您可以通过在类定义之后添加m_instance成员的定义来修复您的错误。

template<typename T>
T* Singleton<T>::m_instance = nullptr;

对于类模板,在头文件中添加static成员的定义是可以的,并且不会导致ODR冲突。

但是,正如其他人建议的那样,最好将getInstance()定义更改为

static T& getInstance() 
{
    static T instance;
    return instance;
}

c++ 11甚至保证局部static函数变量instance的创建将是线程安全的。

静态成员总是只需要初始化一次,包括那些来自模板实例化的成员。

如果你真的喜欢,你可以用局部静态来避免这种情况:

template <typename T>
T *Singleton<T>::getInstance() {
  // Will be lazy initialized on first call (instead of startup) probably.
  static T instance;
  return &instance;
}

或:

// No need to use pointers, really...
template <typename T>
T &Singleton<T>::getInstance() {
  static T instance;
  return instance
};

如果你真的想使用单例,并且你真的确定你想使用模板化的单例,你可能想使用Scott Meyer的单例方法:

template <typename T>
class Singleton
{
public:
   static Singleton<T>& getInstance() {
       static Singleton<T> theInstance; 
       return theInstance;
   }
private:
   Singleton() {}
   Singleton(const Singleton<T>&);
   Singleton<T>& operator=(const Singleton<T>&);
};

指针被标准初始化为NULL,为什么我需要这样做显式初始化?

你不需要。

template <typename T>
T* Singleton<T>::m_instance;

作为静态&全局变量默认为零初始化

具有静态存储时间(3.7.1)或线程存储时间(3.7.2)的变量应进行零初始化(8.5)

其他人已经回答了如何修复代码,但您的问题也是关于推理的。通过解释,你所纠结的是声明和定义之间的区别。这一行:

static T* m_instance;

你声明m_instance有一个名字,但是你还没有定义这个空间。您添加的那行代码定义了空格

最新更新