你目前正处于脱机状态,正在等待 Internet 重新连接

引用计数的规则

注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。

点击这里察看该文章的英文版: 104138
概要
在组件对象模型中,接口的生存时间是通过引用计数控制的。通过继承 IUnknown AddRef() 和 Release() 成员函数进行操作的接口引用计数。AddRef() 成员递增接口的引用计数和 Release() 方法减少它。一旦接口的引用计数将转到零,不再有任何有效的指针,该接口。如果上的所有对象的接口引用计数为零,然后该对象可以被释放因为不再有任何指向该对象的指针。
更多信息

引用计数的规则

下面的列表是一份引用计数 (来自 83 和 84 OLE 2.0 规范的页) 必须遵循的规则。在这篇文章可帮助阐明在规则中添加小的代码示例。

  1. 一个接口指针的每个新副本必须的 AddRef () 应该并且每个销毁的接口指针必须是想除外 () 的发布位置之后的规则明确否则允许。

    1. 函数在输出参数: 的调用方必须 AddRef() 实际参数,因为它将释放由被调用方会 () 时该 out-value 存储在它的上面。
            LPOLEOBJECT lpObject;         .         .  // Get pointer to IOleObject.         .      LPVIEWOBJECT lpView = lpObject;      lpObject->AddRef()      // GetViewObject is a theoretical function that takes a      // pointer to anything derived from IUnknown, and then      // returns a pointer to IViewObject in the same variable      // passed as the parameter. The AddRef() above is needed so      // that the original pointer to IOleObject is not freed.      GetViewObject(lpView);								
    2. 获取一个全局变量: 的鼠标指针在全局变量中的现有副本从提取一个接口指针的本地副本必须独立地计算在内,因为调用函数的引用可能仍处于活动状态的本地副本时销毁中全局副本。
            void function()      {      // Get a pointer to IOleObject from a global variable.      LPOLEOBJECT lpOleObject = glpObject;      // This AddRef() is needed so that the interface      // pointed to by the global variable, glpObject,      // does not get released by a different part of      // the applications code.      lpOleObject->AddRef();         .         . // use lpOleObject;         .      lpOleObject->Release();      }								
    3. 新的精简的空气合成的指针: 合成使用特殊内部的知识,而不是从某些其他来源获取它必须执行新合成指针上的初始 AddRef() 一个接口指针的函数。 重要的此类例程的示例包括实例创建例程,IUnknown::QueryInterface,等的实现。
            STDMETHDOIMP IUnknown::QueryInteface( REFIID iidInterface,                                         LPVOID FAR *ppvObj)      {      *ppvObj = NULL;      SCODE sc = E_NOINTERFACE;      if (iidInterface == IUnknown)          {          *ppvObj = this;          // This AddRef() is needed because a new pointer          // was just created.          AddRef();         sc = S_OK;          }      return ResultFromScode(sc);      }								
    4. 返回一个在内部存储的指针的副本: 被调用方后返回指针具有不知道如何与其生存期内相关的内部存储副本的指针。因此,被调用方必须的 AddRef() 指针返回到它之前复制。
            // m_lpOleObject is a private member variable of a C++ class.      // GetOleObject is a member function to return access to this      // pointer.      void GetOleObject (LPVOID FAR *ppObject)      {          *ppObject = m_lpOleObject;          // This AddRef() is needed due to this rule.          m_lpOleObject->AddRef();       }								
  2. 特殊的一段代码的有关开始和结尾的两个或更多个副本的接口指针的生存期的关系的知识可以允许 AddRef()/Release() 对以被忽略。

    1. 中-参数函数: 一个接口指针,该实参作为传递给函数指针的该副本中是否包含嵌套中,用来初始化值指针的生存期。因此,实际参数不需要单独计算的引用。
            void function (LPOLEOBJECT lpOleObject)      {      // Can use lpOleObject in this function      // without doing AddRef() and Release().      }								
    2. 从包括返回值的函数的输出参数: 设置输出参数,函数本身由规则 1 必须具有一个稳定的副本的接口指针。在退出,负责释放鼠标指针从被调用方传输到调用方。因此,out 参数需要引用计数。
            LPVIEWOBJECT lpView;      HERROR hErr = lpOleObject->QueryInterface(IID_IViewObject,                                                (LPVOID FAR *)lpView);      if (hErr = NOERROR)          {          // The QueryInterface succeeded. lpView does not have          // to be AddRef()'d because it has already been done          // by the QueryInterface method.          }								
    3. 本地变量: 一个函数实现清楚地具有 omniscient 知识的每个堆栈帧上分配的指针变量的生存期。因此,它可以省略冗余 AddRef()/Release() 对使用这些知识。
            void function()      {      LPOLEOBJECT lpTempObject;         .         .         .      lpTempObject = lpObject;         .         .  // lpTempObject can be used         .  // without reference counting as long as         .  // it is known that the lifetime of lpObject         .  // outside of this function call.         .      }								
    4. Backpointers: 某些数据结构是包含 A 和 B,每个都有另一个指向这两个组件的性质。如果一个组件 (A) 的生存期知道它包含在其他 (B) 的生存时间,然后从第二个组件指针回到第一个 (从 B 到 A) 需要不进行引用计数。通常,避免否则创建周期是十分重要的维护适当的释放行为。
2.00 3.50 4.00

属性

文章 ID:104138 - 上次审阅时间:12/03/2003 16:09:55 - 修订版本: 3.1

Microsoft OLE 2.0, Microsoft OLE 4.0

  • kbmt kbprogramming KB104138 KbMtzh
反馈