ATV*_*ATV 4 c++ macos singleton design-patterns c++11
Meyers Singleton是否适用于具有动态库的场景?
即一个库定义单例,其他人使用它,每个库都在自己的编译单元中?
(我想这没关系,但具体的架构是OS X上的框架应用程序)
我正在使用vanilla Meyers Singleton模式:Instance()在实用程序类的头文件中内联定义了以下方法(在动态库中定义):
static Logger& Instance()
{
static Logger singletonInstance;
return singletonInstance;
}
Run Code Online (Sandbox Code Playgroud)
复制构造函数并被operator=声明为私有而未实现,所以我们应该很好,对吧?
现在,如果我链接从主应用程序定义单例的库,我可以看到构造函数被多次调用..具有不同的地址this和所有奇怪的我没有实际单例但是类的多个实例.
所以我想知道动态库方法是否搞砸了Meyers单例,或者每个编译单元 - 库,主应用程序 - 包含单例的标题(有效地声明和定义 Instance()方法)将得到" 它自己的单例"实例 "?
真的不太清楚我的观察结果如何,所以任何提示都非常赞赏!
您需要在标头中声明 Instance,然后在动态库中定义它(可能与Logger定义的相同).你需要放弃static.Instance如果您使用可见性工具,则需要确保具有默认可见性.
根据您的描述,听起来您已经在标题中定义了此功能.这将为每个包含头部的人提供他们自己的私有定义Instance,从而为他们自己的static Logger内部私有定义Instance.
你可以声明Instance inline,这会给你所期望的所有语义(与在标题中声明和在dylib中定义相同).但我的建议是只做内联来确认我告诉你的是正确的(这很容易),然后勾勒出一个dylib(并再次确认).
概述后,您的设计应该可以正常工作.
话虽这么说,它只能保证在C++ 11中工作.也就是说,本地静态在C++ 98/03中不是线程安全的,但在C++ 11及更高版本中.但是,在OS X上,即使在C++ 03语言模式下,它们也是线程安全的扩展.
另一个警告:如果您Instance()在atexit链中(或在全局对象的析构函数中)访问,则可能会在破坏静态本地singletonInstance内部后发生访问Instance(),从而导致未定义的行为.如果你没有注册atexit(),如果你的全球析构函数没有打电话Instance(),你就是安全的.否则你不是.如果您不安全,可以故意泄漏它:
Logger& Instance()
{
static Logger* singletonInstance = new Logger;
return *singletonInstance;
}
Run Code Online (Sandbox Code Playgroud)
这可能会导致一些内存泄漏检查程序报告误报(或者根据您的观点,它们可能是真正的正面),这令人恼火.