我有两位经理(单身人士):
我认为破坏单身的顺序是不确定的。 如何避免管理者遭到破坏时的不匹配?有可能吗?
这是我对单身人士的典型实施:
class Manager : private boost::noncopyable
{
private:
struct singleton_deleter { void operator () (Manager* m) { delete m; } };
friend struct Manager::singleton_deleter;
private:
boost::mutex singleton_mutex;
boost::shared_ptr<Manager> singleton_instance;
public:
static Manager& instance()
{
if(!(bool)Manager::singleton_instance)
{
boost::mutex::scoped_lock lock(Manager::singleton_mutex);
if(!(bool)Manager::singleton_instance)
Manager::singleton_mutex.reset(new Manager, Manager::singleton_deleter());
}
return *Manager::singleton_instance;
}
private:
Manager() { this->lic = LicManager::instance().getLicense(); }
~Manager() { LicManager::instance().releaseLicense(this->lic); }
};
答案 0 :(得分:1)
请注意,由于destruction order of static objects in C++是其构造顺序的the reverse,因此您可以使一个单例的构造函数首先构造它依赖的另一个单例作为函数本地静态对象。例如:
LicManager & LicManager::instance() {
static LicManager licenceManager;
return licenceManager;
}
Manager & Manager::instance() {
static Manager manager(LicManager::instance());
return manager;
}
另一种方法是使用shared_ptr
来共享单身人士的所有权,执行销毁订单。让instance()
返回shared_ptr
而不是引用。在您的使用案例中,将LicManager::instance()
的返回值(例如shared_ptr<LicManager>
)存储在Manager
对象中。这会强制LicManager
在Manager
的生命周期内保持活动状态,即使全局范围中相应的LicManager
共享指针已被销毁。
编辑正如评论中指出的那样,另一种解决方案是只拥有一个拥有所有其他超级单身并控制初始化/销毁顺序的超级单身。
答案 1 :(得分:1)
将单例实例存储为访问器函数的静态局部变量,该函数返回对它的引用。换句话说,使用 Construct On First Use Idiom 。
然后从单例B的构造函数中调用单例A的访问器函数。这样可以确保单A
在B
之前构造,从而确保A
是B
在{{1}}之后被摧毁。
这种模式的变体是使用 - 而不是函数本地静态对象 - 一个函数本地静态原始指针指向动态对象,它在终止时泄露。这种方法不需要单例的构造函数来调用另一个的访问者,但当然内存分析器会抱怨。这个想法是单例永远不会被破坏,所以你可以在其他静态对象的析构函数中自由地依赖它。
它是否真的是一个如此限制的模式,你不能将两个不同的类实现为单身?如果这是真的,单身看起来像一个无用的模式......
Singleton是一种非常严格的模式,有些人可能认为它没用。但是你不可能有两个不同的单身人士类。