5

假设我有以下架构:

  • Dodo单例类libdodo
  • 主程序已链接libdodolibponny;主程序调用Dodo::instance()
  • Ponnylibponny创建类。它有Dodo单例的标题

主窗口.cpp

    #include "shared/dodo/dodo.h"
    // ...
    Dodo::instance()->setNumber(91);

然后,在这个调用之后,Ponny类(ponny.cpp)被创建

ponny.cpp

    #include "shared/dodo/dodo.h"
    // ...
    bool is = (Dodo::instance()->number() == 91);
    // Will `is` be true?

那么,我可以这样做吗?

4

2 回答 2

3

由于单例的行为定义位于其库中,这意味着单例实例将是唯一的,并且将存在于创建它的编译单元中。

假设在libdodothere is Dodo.cpp,你有:

static Dodo& Dodo::instance()
{
    static Dodo dodo;
    return dodo;
}

请注意,局部静态变量在第一次执行到达它们的声明时被初始化,所以在这种情况下Dodo::instance是第一次调用时,所以你很可能不会遇到像这样的单例延迟初始化的任何问题。

这里唯一起作用的是线程安全,因为当更多线程Dodo::instance()第一次调用时可能会出现竞争条件。有关更多信息,我建议您阅读:
这个问题:单例和多线程
这篇文章:C++ 范围内的静态初始化不是线程安全的,这是故意的!
这个问题也可以帮助你: Thread safe lazy construction of a singleton in C++


另请注意,在 C++11(第 6.7.4 节)中,静态变量的初始化保证是线程安全的:

如果在变量初始化时控制同时进入声明,则并发执行将等待初始化完成。

这意味着像这样的惰性初始化变得有点防弹;)

于 2013-01-30T15:35:35.847 回答
2

单例实例是全局的。全局变量可以跨 DLL/共享对象边界共享,如果这确实是您所要求的。

您还需要了解一个定义规则,它保证了这个类确实只有一个定义,因此类中的任何静态成员都只有一个实例。

于 2013-01-30T16:11:43.053 回答