我的单例模板真的是单例吗?
Is my singleton template really a singleton?
有人告诉我,我的单例模板可能不是真正的单例,因为有办法用它创建多个对象。当我问如何解决它时,我被忽略了。这就是为什么我来这里问我的单例模板类真的是单例吗?
#ifndef SINGLETON_H_
#define SINGLETON_H_
template <class T>
class Singleton
{
private:
static T* instance;
protected:
Singleton<T>( )
{
}
public:
static T* getInstancePtr( )
{
if ( instance == 0 )
instance = new T( );
return instance;
}
};
template <class T> T* Singleton<T>::instance = 0;
#endif
然后由我希望成为单例的类继承,如下所示:-
class Console : public Singleton< Console >
{
};
您已经将默认构造函数protected
.派生类可以访问它,因此这将编译:
Console c1, c2;
您无法保证它是单例的一个简单原因是由于线程安全。
如果两个或多个线程同时调用 getInstancePtr,则最终可能会有两个或多个实例,具体取决于线程交换。
使用局部静态变量来实现单例模式:
template <class T>
class Singleton
{
static T* getInstancePtr( )
{
static T instance; // <-- HERE
return &instance;
}
};
除了更少的代码外,它还保证了线程安全。 它将在第一次调用Singleton<X>::getInstancePtr()
时构造,连续的调用将获得一个实例。
或者,如果您希望每个线程一个实例,则可以改用thread_local
:
template <class T>
class Singleton
{
static T* getInstancePtr( )
{
thread_local T instance; // <-- HERE
return &instance;
}
};
我使用了与您相同的单例模板,但将其留给用户来创建私有构造函数和析构函数。用户将不得不与单例类交朋友,但它接近我想要的,并且可以用作单例。它(还不是线程安全的),但它"解决"了多实例问题。
要在多线程环境中工作,您需要不同的解决方案。必须使用特定的语言功能来确保在存在多个线程的情况下仅创建对象的一个实例。更常见的解决方案之一是使用双重检查锁定习惯用法来防止单独的线程同时创建单一实例的新实例。
除了多线程的任何问题之外,还有一种情况我可以创建两个实例。通过初始化下面的类控制台
class Console : public Singleton< Console >
{
};
这样
Console c1;
我最终得到了两个控制台实例,一个在 Singleton 类中保存的实例指针中,另一个在 c1 对象本身中。我通过将 Singleton 类更改为以下内容来解决此问题。
#ifndef SINGLETON_H_
#define SINGLETON_H_
template <class T>
class Singleton
{
private:
static T* instance;
protected:
Singleton<T>( )
{
if ( instance == 0 )
instance = static_cast<T*>(this);
}
public:
static T* getInstancePtr( )
{
return instance;
}
};
template <class T> T* Singleton<T>::instance = 0;
#endif
但是,除了多线程问题之外,我现在更加确定我的单例类不太可能导致多个实例。
- 为什么在单例中,检查类==空?
- C++ 实现模板单例类时出现链接错误
- 在类中存储单例的指针
- C++中的单例实现在调用 getInstance 函数时不会产生相同的类实例
- 具有非默认构造函数的单例类
- 使用 std::call_once 实现类似单例的功能
- 这是MSVC 2013中具有共享PTR的单例的正确实现吗?
- 这是一个有效的单例类吗?
- Meyers与[[gnu::p ure]]一起使用的单例有UB吗?
- 单例中的所有内容都是静态的吗
- 这是单例模式的正确实现吗?
- 这是在C++中创建单例类的正确方法吗?
- 我的单例模板真的是单例吗?
- 我可以在编译期间从 gcc 获取单例的地址或链接时吗?
- 这是单例模式的示例吗?
- 当周围有线程时,创建类的许多实例会失败吗?- 单例模式
- 这个单例实现有问题吗
- 这种c++单例模式和方法公开是一种好的实践吗?
- 有人能确认一下这是否是一个线程安全的单例实现吗?
- 我应该使用单例硬件管理吗?