首先,正如其他人所说,对此的明显(也是最好的)答案是单例。但是,由于您添加了多线程要求:有两种解决方案,具体取决于对象是否将通过使用单例的代码进行修改。(根据您的描述,我认为没有。)如果不是,那么使用单例的“幼稚”实现就足够了,并确保在启动线程之前初始化单例。如果在您进入 main 之前没有启动线程(否则我认为这是不好的做法),那么类似以下的内容在很大程度上就足够了:
class Singleton
{
static Singleton const* ourInstance;
Singleton();
Singleton( Singleton const& );
Singleton& operator=( Singleton const& );
public:
static Singleton const& instance();
};
并在实施中:
Singleton const* Singleton::ourInstance = &Singleton::instance();
Singleton const&
Singleton::instance()
{
if ( ourInstance == NULL ) {
ourInstance = new Singleton;
}
return *ourInstance;
}
不需要锁定,因为一旦线程启动,没有线程将修改任何内容。
如果单例是可变的,那么您必须保护对它的所有访问。你可以做类似上面的事情(
const
显然没有 ),并将锁定留给客户端,但在这种情况下,我更喜欢锁定instance
函数,并返回一个std::shared_ptr
带有释放锁的删除器,这是获取的在instance
函数中。我认为像下面这样的东西可以工作(但我从来没有真正需要它,所以没有尝试过):
class Singleton
{
static Singleton* ourInstance;
static std::mutex ourMutex;
class LockForPointer
{
public:
operator()( Singleton* )
{
Singleton::ourMutex.unlock();
}
};
class LockForInstance
{
bool myOwnershipIsTransfered;
public:
LockForInstance
: myOwnershipIsTransfered( false )
{
Singleton::ourMutex.lock();
}
~LockForInstance()
{
if ( !myOwnershipIsTransfered ) {
Singleton::ourMutex.unlock();
}
}
LockForPointer transferOwnership()
{
myOwnershipIsTransfered = true;
return LockForPointer();
}
};
public:
static std::shared_ptr<Singleton> instance();
};
和实施:
static Singleton* ourInstance = NULL;
static std::mutex ourMutex;
std::shared_ptr<Singleton>
Singleton::instance()
{
LockForInstance lock;
if ( ourInstance == NULL ) {
ourInstance = new Singleton;
}
return std::shared_ptr<Singleton>( ourInstance, lock.transferOwnership() );
}
这样,相同的锁用于检查 null 和访问数据。