Meyers Singleton是否可以在带有动态库的场景中使用?
是一个库定义单例,其他库使用单例库,每个库都在自己的编译单元中?
(我想没关系,但是特定的体系结构是在OS X上带有框架的应用程序)
我使用的是香草Meyers Singleton模式:Instance()
在实用程序类(在动态库中定义)的头文件中内联定义以下方法:
static Logger& Instance()
{
static Logger singletonInstance;
return singletonInstance;
}
复制构造函数并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;
}
这可能会导致某些内存泄漏检查程序报告误报(或者,根据您的观点,它们可能是真正的肯定),这很令人讨厌。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句