c++ template singleton static pointer initialization in header file

左心房为你撑大大i 提交于 2019-12-28 07:01:09

问题


What is wrong with this implementation in header file?

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;
};

I use it like this:

typedef Singleton<MyClass> MyClassSingleton;

I get linker error:

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

When I add

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

it works, but I worry on two things:

  1. Static member should be defined in .cpp file in order to have only one instance in all compilation units, even if you include the header file into 10 source files
  2. Pointers are being initialized to NULL by standard, why I need to explicitly initialize?

回答1:


You can fix your error by adding a definition for the m_instance member after the class definition.

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

For class templates, it's OK to add the definition of static members within the header itself, and won't lead to ODR violations.

But, as others have suggested, it's best to change you getInstance() definition to

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

C++11 even guarantees that the creation of the function local static variable instance will be thread-safe.




回答2:


Static members always need to be initialized exactly once, including those from template instantiations.

You can avoid this with local statics if you really like:

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

Or:

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



回答3:


If you're really want to use a singleton, and you're really sure you want to use a templated singleton, you may want to use Scott Meyer's singleton approach:

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>&);
};



回答4:


Pointers are being initialized to NULL by standard, why I need to explicitly initialize?

You don't need.

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

This will suffice as static & global variables are zero initialized by default

Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place.




回答5:


Others have answered how to fix the code, but your question was also about the reasoning. By way of explanation, what you are struggling with is the difference between declaration and definition. In this line:

static T* m_instance;

You are declaring that there is a name for m_instance, but you have not defined the space. The line of code you added defines the space.



来源:https://stackoverflow.com/questions/23690416/c-template-singleton-static-pointer-initialization-in-header-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!