我已经实现了一个基于c ++ 11的单例。但是在某些情况下可以多次调用构造函数。
该类将被编译为静态库,并由其他lib(多个lib)使用。系统是一个多线程系统(在Android HAL级别运行)
/// .h文件:
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
/// .cpp文件
Logger::Logger()
{
ALOGE("OfflineLogger create");
}
Logger::~Logger()
{
}
它应该创建一次,例如:
03-21 01:52:20.785 728 4522 E : OfflineLogger create
但是我可以看到它已被创建不止一次
03-21 01:52:20.785 728 4522 E : OfflineLogger create
03-21 01:52:20.863 728 2274 E : OfflineLogger create
03-21 01:52:20.977 728 2273 E : OfflineLogger create
03-21 01:52:26.370 728 4522 E : OfflineLogger create
问题:
- 我的单件设计有什么问题吗?这是一个线程安全的问题吗?
否。函数本地static
变量的初始化保证是标准的线程安全。
- 好像我的单身人士在一个范围内工作正常,但每个包含我的单身人士的lib都会创建自己的单身人士,这样我的单身人士就不再是“单身人士”了。问题是由每个动态链接引起的,所以“staic veriable”变成“本地静态”吗?可能吗?如果是这样,如何解决
这是正确的结论。
而不是创建包含单例实现的静态库,使其成为动态库。
单身人士很难,尤其是共享图书馆。
每个共享库都有一个非共享库的独立副本。没有额外的照顾,每个人都会有一份单身人士的副本。
为了拥有非平凡的单身人士,我必须做的就是
typeid(T).name()
密钥,并且类型擦除构造和销毁代码。 LibSingleton返回一个引用计数RAII对象。这允许在几乎任何地方使用非常简单的单身人士。
template<class T>
class singleton {
public:
static T& Instance() {
static auto smart_ptr = LibSingleton::RequestInstance(
typeid(T).name(),
sizeof(T),
[](void* ptr){ return ::new( ptr ) T{}; },
[](void* ptr){ static_cast<T*>(ptr)->~T(); }
);
if (!smart_ptr)
exit(-1); // or throw something
return *static_cast<T*>(smart_ptr.get());
}
protected:
singleton() = default;
~singleton() = default;
private:
singleton(singleton&&) = delete;
singleton& operator=(singleton&&) = delete;
};
使用看起来像:
struct Logger : LibSingleton::singleton<Logger> {
friend class LibSingleton::singleton<Logger>;
void do_log( char const* sting ) {}
private:
Logger() { /* ... */ }
};
这是一个想法:不是使用单例,这在您的环境中既是一个难题,又已知在测试和维护方面存在问题,只需将代码设计为仅创建一个有问题的对象。
静态变量应该移动到.cpp文件。
简单的方法是仅在.h中保留getInstance()的声明并将实现移动到.cpp文件。
可能是您的头文件被多次定义(如果多个文件是including
这个头文件就是这种情况。尝试在头文件周围添加一个保护,以防止它被重新定义,如果它已经被定义一次。
根据您的C ++编译器,您实际上只需将#pragma once
添加为文件中的第一行,就像这样
#pragma once
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
预期的效果是最常用的替代方案,即添加像这样的宏定义
#ifndef LOGGER_H
#define LOGGER_H
class Logger
{
public:
/// Return the singleton instance of Logger
static Logger& GetInstance() {
static Logger s_loggerSingleton;
return s_loggerSingleton;
}
private:
/// Constructor
Logger();
/// Destructor
~Logger();
}
#endif LOGGER_H