技巧:显式管理引用计数(50分)

  • 主题发起人 主题发起人 shenloqi
  • 开始时间 开始时间
S

shenloqi

Unregistered / Unconfirmed
GUEST, unregistred user!
这只是一个关于引用计数的例子,Delphi的Interface以及string还有动态数组等等都是
自动处理引用计算的,有时候会希望在变量超出范围之后保留一个指向一个字符串或接口
的引用。(例如:可能需要将一个接口与一个TListview中的每一个元素联系起来,好像
有一些牵强,不过我觉得主要是用来学习引用计数的,呵呵)可以通过显式地管理引用计
算来做到这一点。存储接口时,务必把它转换为IUnknown,调用_AddRef,并将IUnknown
引用转换为一个原始指针。析取数据时,将指针类型转换为IUnknown,然后可以用as运算
符来将接口转换为任何想要的类型(或只让Delphi释放该接口)。下面是一个在ListView
中存储接口的例子。(非本人创作,只是共同学习)

代码:
{-----------------------------------------------------------------------------
  Procedure: RefIUnknown
  Author:    slq
  Date:      22-三月-2002
  Arguments: const Intf: IUnknown
  Result:    Pointer
  Purpose:   保存接口到一个指针,增加引用计数。
-----------------------------------------------------------------------------}
function RefIUnknown(const Intf: IUnknown): Pointer;
begin
  //增加引用计数
  Intf._AddRef;
  //保存接口指针
  Result := Pointer(Intf);
end;

{-----------------------------------------------------------------------------
  Procedure: ReleaseIUnknown
  Author:    slq
  Date:      22-三月-2002
  Arguments: P: Pointer
  Result:    None
  Purpose:   释放保存在指针中的接口
-----------------------------------------------------------------------------}
procedure ReleaseIUnknown(P: Pointer);
var
  Intf: IUnknown;
begin
  Pointer(Intf) := P;
  //Delphi会在子程序结束后自动释放借口
end;

{-----------------------------------------------------------------------------
  Procedure: TForm1.Button1Click
  Author:    slq
  Date:      22-三月-2002
  Arguments: Sender: TObject
  Result:    None
  Purpose:   增加接口到列表
-----------------------------------------------------------------------------}
procedure TForm1.Button1Click(Sender: TObject);
var
  Item: TListItem;
begin
  Item := ListView1.Items.Add;
  Item.Caption := 'Hello, World!';
  Item.Data := RefIUnknown(GetIntf as IUnknown);
end;

{-----------------------------------------------------------------------------
  Procedure: TForm1.ListView1Deletion
  Author:    slq
  Date:      22-三月-2002
  Arguments: Sender: TObject
Item: TListItem
  Result:    None
  Purpose:   释放列表项目的时候一定要记得释放接口
-----------------------------------------------------------------------------}
procedure TForm1.ListView1Deletion(Sender: TObject
Item: TListItem);
begin
  ReleaseIUnknown(Item.Data);
end;

{-----------------------------------------------------------------------------
  Procedure: TForm1.ListView1Click
  Author:    slq
  Date:      22-三月-2002
  Arguments: Sender: TObject
  Result:    None
  Purpose:   用户对列表的操作就相当于对接口的操作
-----------------------------------------------------------------------------}
procedure TForm1.ListView1Click(Sender: TObject);
var
  Intf: IMyInterface;
begin
  Intf := IUnknown(ListView1.Selected.Data) as IMyInterface;
  Intf.DoSomethingUseful;
end;

同样的方法可以对于字符串等使用,例子就省略了(基本同上)。
 
你真的是一个好心人。
 
谢谢夸奖,只是我觉得这些东西大家一起了解才是正确的做法:)
 
赶快复制粘贴了。。 哈哈哈。
 
我看了好几遍你的帖子了,真的很感谢,希望你能早日找到满意的工作!
 
谢谢楼上的祝福。

可能大家认为这个技巧没有什么用途,但是实际上并不是这样的,比如说要在TListView
里面存储Item的说明等等,就可以利用这个特征让每一个Item的Data对应String的指针,
甚至还可以对应于指针列表的指针。
 
多人接受答案了。
 
后退
顶部