我们如何将 Phoenix Singleton 放在同一个地址? C++

How we place Phoenix Singleton on same address? C++

下面的代码说明了 Phoenix Singleton described in Andrey Alexandrescu's 现代 C++ 设计书。

Singleton& Instance()
{
   if (!pInstance_)
   {
   // Check for dead reference
      if (destroyed_)
      {
         OnDeadReference();
      }
      else
      {
   // First call—initialize
         Create();
      }
   }
return pInstance_;
}

void Singleton::OnDeadReference()
{
// Obtain the shell of the destroyed singleton
   Create();
// Now pInstance_ points to the "ashes" of the singleton
// - the raw memory that the singleton was seated in.
// Create a new singleton at that address
   new(pInstance_) Singleton;
// Queue this new object's destruction
   atexit(KillPhoenixSingleton);
// Reset destroyed_ because we're back in business
   destroyed_ = false;
}

static void Create();
{

// Task: initialize pInstance_
   static Singleton theInstance;
   pInstance_ = &theInstance;
}

void Singleton::KillPhoenixSingleton()
{
// Make all ashes again
// - call the destructor by hand.
// It will set pInstance_ to zero and destroyed_ to true
   pInstance_->~Singleton();
}


virtual ~Singleton()
{
   pInstance_ = 0;
   destroyed_ = true;
}

Singleton* Singleton::pInstance_ = 0;
bool Singleton::destroyed_ = false;

书中引述:

Let's analyze the flow of events. During the application exit sequence, Singleton's destructor is called. The destructor resets the pointer to zero and sets destroyed_ to true. Now assume some global object tries to access Singleton again. Instance calls OnDeadReference. OnDeadReference reanimates Singleton and queues a call to KillPhoenixSingleton, and Instance successfully returns a reference to a valid Singleton object. From now on, the cycle may repeat.

我的问题是 - 如果我们在析构函数中分配给指针 pInstance_ = 0,而不是它分配给一个本地静态引用,该引用应该在该点被删除,我们如何在 0 地址放置一个新对象?请告诉我我遗漏了什么。如果有人能向我解释流程,我将不胜感激。谢谢

"Phoenix" 这个名字来自传说中的鸟,它死去、着火并从灰烬中重生。

在这种情况下,是的,Singleton 可以死掉,析构函数运行,pInstance 变成 nullptr,然后它就消失了 - 直到它需要复活。发生这种情况时,Createnew (pInstance) Singeton 重新创建对象之前使 pInstance 非空。

[编辑] 您需要了解对象生命周期和存储持续时间的规则。显然,对象的存储必须在创建对象之前分配,并且在对象被销毁之前不能释放存储。两者之间的间隔称为 存储持续时间 。现在,有static storage duration这样的东西。在程序退出之前不会回收此类存储,即使该存储中的对象已被销毁。在命名空间范围内定义的变量 ("globals") 和 static 变量具有此静态存储持续时间。

因此,theSingleton 的存储具有静态存储持续时间,即使存在 destroyed 的对象,pInstance 也可以指向此存储。请注意,destroyedpInstance 变量本身也具有静态存储持续时间,因为它们是全局变量。