赞
踩
原文
使用引用计数
来管理对象
的生命期
,允许多个客户
无需相互协调
就获取并释放单个对象
.
只要客户对象
遵守某些使用规则
,就会有效管理该对象
.这些规则
指定了如何管理对象间
的引用.(COM
不指定对象
内部实现,尽管这些规则
是对象内策略
的合理起点.)
从概念上讲,可按在包含所有保存
接口指针的内部计算状态
的指针变量
中驻留
,来对待接口指针
.包括内存位置
中,内部处理器寄存器
中,及程序生成
的变量和编译器
生成的变量
.
赋值或初化
指针变量,涉及创建
现有指针的新副本
.如果某个变量
中有个(赋值/初化
)指针副本
中使用
的值,则现在有两个
.
与变量
自身析构
一样,赋值
指针变量,也会析构
变量中的指针副本
.(也即,析构变量
所在的域
(如栈帧
))
从COM
客户角度来看,总是对每个接口
执行引用计数
.客户
绝不应假定,对所有接口,对象
使用相同的计数器
.
默认
是,必须为接口指针
的每个新副本
调用AddRef
,且除非以下规则
允许,必须对接口指针
的每个析构
调用Release
:
1,函数
的传入出(进出,inout)
参数.当在参数
上存储out
值时,因为在调用Release
释放它,来实现代码
时,调用者必须在参数
上调用AddRef
.
2,取
全局变量.从全局变量
中的指针的现有副本
创建接口指针
的局部副本
时,必须在局部副本
上调用AddRef
,因为在局部副本
仍有效时,另一个函数可能会析构
全局变量中的副本
.
3,从"薄层"
合成的新指针
.使用特殊内部知识
合成接口指针
而不是从其他源
取接口指针
的函数
,必须在新合成
的指针,初始调用AddRef
.
重要示例
包括实例创建例程
,QueryInterface
的实现
等.
4,提取
内部存储指针的副本
.函数提取由调用对象
在内部
存储指针的副本
时,在函数
返回前,该对象代码
必须对指针
调用AddRef
.
提取
指针后,原对象
不能确定
其生命期
与指针内部存储副本
生命期的关系
.
默认情况的唯一例外
,要求管理代码
知道,对象
上同一接口指针
的多个副本
的生命期关系
,且只需通过禁止
引用计数更改
为零
,来确保不会析构对象
.
一般
有如下
两种情况:
1,如果已存在
指针的一个副本
,在第一个
副本仍存在时,随后又创建
了稍后析构的第二个副本
,则可省略
调用第二个
副本的AddRef
和Release
.
2,如果存在指针的一个副本
并创建了第二个副本
,然后在第二个
副本前析构
了第一个副本
,则可省略调用第二个
副本的AddRef
和第1个
副本的调用Release
.
下面是具体示例
,前两种情况特别常见
:
1,函数的输入(in)参数
中.用来初化值
的指针,有按参数
传递给函数
的接口指针
的副本
,因此不需要对参数
使用单独引用计数
.
2,函数包括返回值
的输出(out)参数
.要设置out
参数,函数必须有接口指针
的稳定副本
.返回
时,调用者
负责释放
指针.因此,out
参数不需要单独
引用计数.
3,局部变量.方法实现
控制栈帧
上分配的每个指针变量
的生命期,并可用它来确定
如何省略
冗余的AddRef/Release
对.
4,后指针
.某些数据结构
包含两个互指
对象的指针
的对象.如果已知第一个
对象的生命期
包含第二个
对象的生命期
,则无需引用计数第二个
对象的指向第1对象的指针
.
一般,避免循环引用
对维护适当的释放
行为非常重要.但是,使用未计数
的指针
时应格外小心,因为处理远程
处理的操作系统部分无法了解此关系
.
因此,最好让后指针
看到第一个指针
的第二个
"友元"对象(从而避免
循环).如,COM
的可连接对象架构
就是这样.
实现或使用引用计数对象
时,应用人工
引用计数也可能很有用,这样可保证函数处理
过程中的对象稳定性
.
实现接口
方法时,可能会调用会减少
对象引用计数
的函数,从而导致过早释放对象
从而失败.
可靠方法
是在实现方法
的开头
插入调用AddRef
,并在方法
返回前调用配对的Release
.
有时,AddRef
和Release
的返回值
可能不稳定,不应依赖它;它们应仅用来调试或诊断
.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。