【问题标题】:Meyers singleton and dynamic librariesMeyers 单例和动态库
【发布时间】:2014-01-30 13:47:28
【问题描述】:

Meyers Singleton 是否在使用动态库的场景中工作?
IE。一个库定义单例,其他库使用它,每个库都在自己的编译单元中?
我想没关系,但具体的架构是在 OS X 上带有框架的应用程序

我正在使用 vanilla Meyers Singleton 模式:以下 Instance() 方法在实用程序类的头文件中内联定义(在动态库中定义):

    static Logger&  Instance()
              {
                 static Logger singletonInstance;
                 return singletonInstance;
              }

复制构造函数和operator= 被声明为私有且未实现,所以我们应该很好,对吧?

现在,如果我从主应用程序链接定义单例的库,我可以看到构造函数被 多次调用.. this 的地址不同,如果没有,我会期待所有的怪异有一个实际的单例,但有多个类的实例。

所以我想知道动态库方法是否搞砸了 Meyers 单例,或者是否每个编译单元(库、主应用程序)都包含单例的标头(有效地声明和定义实例() 方法)会得到“它自己的单例实例”?

真的不太清楚我的观察结果如何,因此非常感谢任何提示!

【问题讨论】:

  • 头文件中的static Logger& Instance() 是否应该用于在其他代码中获取实例?为什么不是extern
  • 那是实际的代码吗?我期待Logger::Instance()..
  • @KarolyHorvath 是的,Instance() 是在单例的头文件中内联定义的。改写问题以使其更清楚..

标签: c++ macos design-patterns c++11 singleton


【解决方案1】:

您需要在标题中声明Instance,然后在动态库中定义它(可能与Logger 的定义相同)。你需要删除static。如果您使用的是visibility tools,则需要确保Instance 具有默认可见性。

根据您的描述,听起来您已经在标题中定义了此函数。这将为包含标题的每个人提供Instance 的私有定义,从而在Instance 中提供static Logger 的私有定义。

您可以声明Instanceinline,这将提供您期望的所有语义(与在标头中声明和在dylib 中定义相同)。但我的建议是只做内联以确认我告诉你的内容是正确的(这很容易),然后勾勒到一个 dylib 中(并再次确认)。

一旦概述,您的设计应该可以正常工作。

话虽如此,它只能保证在 C++11 中工作。也就是说,局部静态在 C++98/03 中不是线程安全的,但在 C++11 及更高版本中是线程安全的。但是,在 OS X 上,即使在 C++03 语言模式下作为扩展,它们也是线程安全的。

另一个警告:如果您在 atexit 链中(或在全局对象的析构函数中)访问 Instance(),则您的访问可能会在 Instance() 内的静态本地 singletonInstance 销毁之后发生,导致未定义的行为。如果你不使用atexit() 注册东西,并且如果你的全局析构函数不调用Instance(),那么你是安全的。否则你不是。如果你不安全,你可以故意泄露它:

Logger&  Instance()
{
   static Logger* singletonInstance = new Logger;
   return *singletonInstance;
}

这可能会导致一些内存泄漏检查器报告误报(或者根据您的观点,它们可能是真报),这很烦人。

【讨论】:

  • 感谢您的澄清!仅在定义中删除static,对吗? IE。从声明中删除它没有任何意义吗?
  • 从函数声明定义中删除staticstatic 在此上下文中表示“文件范围”或“文件专用”。并且您希望此函数的范围是应用程序范围。
猜你喜欢
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-14
  • 1970-01-01
  • 2021-03-02
  • 2019-05-12
相关资源
最近更新 更多