当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++基础入门教程

C++智能指针有效回收方法讲解(2)

这种情况发生在传统的C++类对象中指针成员串行化与反串行化时,例1,是一段带有重载>>与<<操作符,串行及反串行化CJobInst与CJobDef类指针的CArchive类代码,也证明了这点。


  例1:

以下是引用片段:
class CJobDef
  {
  friend CArchive & operator >> (CArchive &ar, CJobDef *def)
  {
  ar >> def->command;
  }
  friend CArchive & operator << (CArchive &ar, CjobDef *def)
  {
  ar << def->command;
  }
  private:
  std::string command;
  };
  class CJobInst
  {
  friend CArchive & operator >> (CArchive &ar, CJobInst *inst)
  {
  inst->m_def = new CJobDef;
  ar >> inst->m_def;
  }
  friend CArchive & operator << (CArchive &ar, const CJobInst *inst)
  {
  ar << inst->m_def;
  }
  private:
  CJobDef *m_def;
  };


  在CJobInst中串行化CJobDef的私有成员m_def涉及到调用CArchive类中适当的<<操作符,重载的<<操作符通过把对象属性串行化进一个永久的存档文件,来实现对CJobDef指针的串行化;反串行化CJobDef指针涉及到构造一个新的对象,并调用>>操作符从存档文件中更新属性。

  解决方案

  引用计数智能指针是由继承自CReferable类一个对象实现的,其包含了一个私有引用计数器及用于修改其值的increaseReferenceCount()与decreaseReferenceCount()方法,而相应的Ref模板类,通过->、*、= 操作符重载,也实现了访问此对象及对生命期的管理。Ref模板对智能指针的赋值操作,会递增对象的引用计数,而它的析构函数会递减计数。智能指针中的对象只当它的引用计数为零时被销毁。在上面的作业调度系统中,CJobDef对象被包装在一个CJobDefPtr类型中,其由以下语句定义:

以下是引用片段:
typedef Ref<CJobDef> CJobDefPtr;


  这个CJobDefPtr类型,正是类CScheduler所用到的类型。当用户提交一个作业到事件作业调度器时,会产生一个CJobDefPtr类型新的对象,且会赋予它CJobDef对象;此后,当作业实例创建时,也正是这个CJobDefPtr类型赋予给了实例。

  在CJobDefPtr类中,赋值=操作符递增了CJobDef对象CReferable基类中的引用计数,而delete操作符递减了这个引用计数。包装在CJobDefPtr对象中的CJobDef对象不会被销毁,直到它的引用计数为零,这也说明了在系统中,没有其他任何对象引用CJobDef对象,它可以安全地被销毁了。

  再次提醒,从作业中创建的作业实例,被包装在一个CJobInst类中。与CJobDef一样,类CScheduler只知道它对应版本的智能指针CJobInstPtr,而此对象的实例也会一直保持到没有对它的引用为止。[Page]

  另外,在系统中,还包括了另外三个特性,以便使调度系统可高效地恢复:

  ⊃; 类CReferable增加了一个tag属性,以唯一地识别每个创建的指针实例,同时有一个getTag()方法可用于访问此属性。

  ⊃; Ref模板类在称为CReferableCache的全局对象缓存中管理它的对象,此全局对象缓存可由其他智能指针对象访问。

  ⊃; Ref模板类添加了一个impersonate()方法,其允许一个智能指针以给定的tag转换为另一个智能指针。

  当一个新的CJobDefPtr或CJobInstPtr被创建时,在CReferable基类构造函数中,会分配给对象唯一的一个tag。这个tag可由几种方式产生,但任一种方式都必须保证在每次软件运行时,都会有一个唯一的ID。一个简单的方案是使用一个静态、全局的计数器对象,其在存档文件中存储了上一次产生的ID,由此可保证甚至在有多个软件实例运行的条件下,都能单调不重复地递增此ID。

  分配给智能指针的tag,唯一地标识出一个指针,而把此tag存入一个存档文件就是对象串行化过程的责任了。对象的串行化过程,可通过CReferable基类的getTag()方法,来访问此tag,接下来,对象的反串行化过程使用此tag,在软件恢复时,来重建正确的对象指针实例引用。下面是反串行化过程必须执行的步骤:

  ⊃; 从存档文件中恢复tag。

  ⊃; 从tag标识的存档文件中,恢复对象属性。

  ⊃; 以此tag为界调用impersonate()方法,恢复正确的指针对象的引用。

共2页 首页 上一页 1 2 下一页 尾页 跳转到
相关内容
赞助商链接