c++ - Meyers 单例和动态库

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

Meyers Singleton 是否适用于有动态库的场景?
IE。一个定义单例的库,其他人使用它,每个都在自己的编译单元中?
(我想这无关紧要,但具体架构是 OS X 上带有框架的应用程序)

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

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

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

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

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

真的不太确定我的观察结果如何,所以非常感谢任何提示!

最佳答案

您需要在 header 中声明 Instance,然后在动态库中定义它(大概是 Logger 定义在)。您需要删除 static。如果您使用 visibility tools,您需要确保 Instance 具有默认可见性.

根据您的描述,听起来您已经在 header 中定义了这个函数。这将为包含 header 的每个人提供他们自己的 Instance 私有(private)定义,因此他们自己对 Instance 中的 static Logger 的私有(private)定义。

您可以声明 Instance inline,这将为所有内容提供您期望的语义(与在 header 中声明和在 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;
}

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

关于c++ - Meyers 单例和动态库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21442758/

相关文章:

c++ - 将访问者模式与模板派生类一起使用

javascript - JavaScript 中的什么机制导致 DOM 或 CSSStyleDeclaration 的变化触发页面重绘?

C++脉冲计数器

css - Firefox 中的字体平滑

c++ - 派生类是否为成员变量分配内存?

eclipse - Eclipse 在 Mac OS X 上使用的默认字体是什么?

python - 在 Mac OS X 下安装 Mathics

.net - 存储库模式中的事务

c++ - 在没有捕获列表的情况下访问 lambda 中的变量

c++ - 我不明白VS2013编译器显示的错误