Singleton实施有什么问题?

时间:2015-07-16 02:20:18

标签: c++ class oop memory singleton

请仔细阅读问题。

我在我需要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

4 个答案:

答案 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复制的问题。我建议您尝试在不同的编译器上使用您的精确代码,看看是否可以在那里重现错误。如果你不能,那可能是编译器问题:因为据我所知,你使用的初始化行确实是初始化静态模板数据成员的正确方法。