请仔细阅读问题。
我在我需要Singleton模式的类型中使用这个基类:
#pragma once
template<typename T>
class singleton
{
private:
static T* g_pInstance;
public:
static T* getInstance() { return g_pInstance; }
public:
singleton() { g_pInstance = (T*)this; }
~singleton() { if(g_pInstance == this) g_pInstance = nullptr; }
};
template<typename T>
T* singleton<T>::g_pInstance = nullptr;
用法(无* cpp文件):
class Any : public singleton<Any> { /* Done */ }
但是,现在我在静态库中使用这样的类有一个奇怪的情况,g_pInstance
指针已经设置为0xccccccc
(没有初始化为零),之前一切都很好。
是什么原因?
更新:编译器:vs 2013 x86
答案 0 :(得分:4)
检查一下这个简单的单例实现 Singleton instance declared as static variable of GetInstance method
这消除了您的实例指针初始化问题。 同意Luu,VC将0xcccccccc的值分配给未初始化的指针。 单身人士很糟糕,受到许多人的批评,但我仍然不能完全避免它:-(
尝试回答为什么在调用getInstance时实例指针不是nullptr。我假设应用程序中有不同的编译单元。如果发布的代码在编译单元A中,则实例指针存在于此A编译单元的静态范围内。我还假设存在一个编译单元B,它具有在编译单元B的静态范围内声明的类Any对象。由于C ++运行时保证仅在同一编译单元内的初始化顺序,而不是跨多个编译单元。编译单元B中的类Any对象的初始化可能在编译单元A中的实例指针初始化之前发生。这将导致在调用getInstance时在实例指针中观察0xcccccccc。
答案 1 :(得分:3)
MSVC在初始化模板静态时遇到了一些问题。这不是你的案件特有的东西 我相信这可能是一个解决方案:
template<> Any* singleton<Any>::g_pInstance = nullptr;
你的单身人士并不完全是线程安全的,但我想你已经知道了: - )
答案 2 :(得分:1)
实现单例而不将其暴露给类,因此您不需要在源代码中初始化它。并使私有构造函数和复制构造函数。我不知道为什么你需要那些铸造的东西。你可以这样做:
#pragma once
template<typename T>
class singleton
{
private:
singleton();
singleton(const singleton&);
public:
static T& getInstance()
{
static T instance;
return instance;
}
};
答案 3 :(得分:0)
我赞同那些抱怨你的“单身”类的人 - 它支持多个实例,所以它不是标准意义上的单身。但是如果我理解你的问题,那么实际上困扰你的是Any::getInstance()
未被nullptr
分配初始化,对吗?
如果是这样,那就是我无法用g ++(GCC)4.8.3,clang版本3.4.2或on ideone复制的问题。我建议您尝试在不同的编译器上使用您的精确代码,看看是否可以在那里重现错误。如果你不能,那可能是编译器问题:因为据我所知,你使用的初始化行确实是初始化静态模板数据成员的正确方法。