如何在C ++中创建一个简单的单例类?

时间:2014-11-20 20:38:11

标签: c++ class singleton

我在这里就stackoverflow做了一些关于这个主题的研究,但我没有找到一个答案,我可以从哪里学习单例类如何工作。我已经知道单例类只能有一个实例。任何人都可以解释我 - 或者链接我一个教程 - 如何创建最基本的单例类并逐行告诉我为什么/它如何工作? 我遇到的麻烦是,我查找的答案和一些教程并没有真正解释为什么我应该将某个变量或函数声明为静态,指针等。

2 个答案:

答案 0 :(得分:2)

<强> Discalimer

通常,应尽量避免使用单例和/或全局对象。应该明确传递函数require的对象。这样可以在并行化代码时通过传递模拟对象,调试和减少争用来轻松测试函数。例如,我的应用程序中唯一的全局对象是记录器(类似于标准I / O流)和特定于线程的事件循环引擎。

使用单例或全局对象的唯一原因是避免在所有函数调用中传递它的麻烦。例如。您不希望通过每次调用传递记录器对象,但是没有必要创建许多本地或成员记录器对象来节省空间和时间。


方法1

最基本的单例是在运行时动态初始化阶段初始化的全局对象,例如:

// singleton.h
class Singleton { /*...*/ };
extern Singleton singleton;

// singleton.cc
#include "singleton.h"
extern Singleton singleton(/*...*/);

好处:

  • 在输入main之前初始化。
  • 线程安全初始化。
  • 非侵入性,不要求班级成为&#34; singleton&#34;。对象singleton什么是单例,而不是类本身。

缺点:

  • main之前可能无法使用某些构造函数参数。

也可以在输入main之前使用此类对象,方法是确保在使用Schwarz Counter进行首次访问之前对其进行初始化(同样的方法std::cout和朋友初始化)。< / p>


方法2

另一种选择是拥有一个指向对象的全局指针。该指针在main的早期初始化,并在main堆栈上创建了一个对象。

E.g:

// singleton.h
class Singleton { /*...*/ };
extern Singleton* singleton;

// main.cc
int main() {
    Singleton the_singleton(/*...*/);
    singleton = &the_singleton;

    // at main end
    singleton = nullptr;
}

与方法1相比的好处。


方法3

C ++ 11中的函数作用域static (gcc在C ++ 11之前做过)对象:

// singleton.h
class Singleton { /*...*/ };
Singleton& get_singleton();

// singleton.cc
Singleton& get_singleton() {
    static Singleton singleton;
    return singleton;
}

方法1的优点和缺点。


方法4

双重检查锁定的单身人士。 Not necessary in C++11,因为函数作用域static 为您进行线程安全初始化。

答案 1 :(得分:2)

  勺子男孩:不要尝试单身课。这是不可能。不良做法。相反......只是试图实现真相。

     

Neo:真相是什么?

     

勺子男孩:没有单身人士。

     

Neo:没有单身人士?

     

Spoon boy:然后你会看到,不仅仅是一个实例的类,只有你需要一个实例。

我想说的是:作为一个班级作者,永远不要强迫这个班级成为单身人士。仅仅因为您认为系统今天只需要一个Logger对象,并不意味着明天您可能不需要两个(例如,一个用于Windows应用程序事件日志,一个用于系统事件日志)。

认为你的thread_pool课应该是单身人士?好吧,我需要一个公平的线程池和我的一个应用程序中的LIFO线程池。

如果要创建N Agent个对象,并且它们都需要共享一个Logger对象,请不要将Logger写为单例 - 而是使用类似:

// agent.h
class Agent {
    ...
    private:
        Logger& GetLogger();
}

// agent.cpp
Logger& Agent::GetLogger() {
    static Logger TheOne;
    return The One;
}

毕竟,Agent需要Logger才能成为单身人士 - 而不是Logger本身!