【问题标题】:How we place Phoenix Singleton on same address? C++我们如何将 Phoenix Singleton 放在同一个地址上? C++
【发布时间】:2018-11-09 09:18:09
【问题描述】:

下面的代码说明了Andrey Alexandrescu's Modern C++ Design book 中描述的Phoenix Singleton

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;

书中引用:

让我们分析一下事件的流程。在应用程序退出序列期间,Singleton 的析构函数被调用。 析构函数将指针重置为零并将destroyed_设置为true。现在假设一些全局对象 尝试再次访问 Singleton。实例调用 OnDeadReference。死引用 重新激活 Singleton 并将对 KillPhoenixSingleton 的调用排队,并且 Instance 成功 返回对有效 Singleton 对象的引用。从现在开始,这个循环可能会重复。

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

【问题讨论】:

  • pInstance_ 声明在哪里?
  • 在底部,向下滚动,它是一个静态指针成员

标签: c++ singleton phoenix


【解决方案1】:

“凤凰”这个名字来源于传说中的鸟,它死了,着火了,从灰烬中重生。

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

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

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

【讨论】:

  • 这是我的问题,create 将它分配给已经被销毁的本地静态对象,它还有地址吗?它是如何工作的?
  • KillPhoenixSingleton() 只为内存还在的对象调用析构函数。
  • 是的,而且在析构函数中,它把指针赋值为0,所以它不再指向同一个内存,下次调用create,它会指向已删除的本地静态,怎么会?还有一个问题,为什么我们要在同一个地址上创建它?还不够创建它吗?
  • @EduardRostomyan:在Create 的下一次调用中,pInstance 被改回指向 destroyed 本地静态。 “已删除”一词具有误导性,因为它暗示 delete。但是,new/delete 用于创建和销毁具有动态存储时长的对象,因此请勿将术语“已删除”与静态存储时长结合使用。
猜你喜欢
  • 2017-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-01
  • 1970-01-01
  • 2018-01-22
相关资源
最近更新 更多