Delphi 中的自动引用计数使用规则


本文整理自网络,侵删。

 
Delphi 用户应该早已经熟悉自动引用计数的概念(ARC),Delphi  很早就开始支持接口、动态数组和字符串的自动引用计数(DCC32、DCC64、DCCOSX),移动编译器则加入对类的自动引用计数支持,因此还加了入弱引用的概念,以管理循环引用。有个预编译条件指令 AUTOREFCOUNT 可以检测当前是否编译器是否启用了自动引用计数。

在启用自动引用计数的情况下,编码发生了以下变化:

对象创建不再需要手工释放,所以下面的代码是没有内存泄露问题的

class procedure TMySimpleClass.CreateOnly;
var
  MyObj: TMySimpleClass;
begin
  MyObj := TMySimpleClass.Create;
  MyObj.DoSomething;
end;
1
2
3
4
5
6
7
class procedure TMySimpleClass.CreateOnly;
var
  MyObj: TMySimpleClass;
begin
  MyObj := TMySimpleClass.Create;
  MyObj.DoSomething;
end;
循环引用需要通过 weak 指示符,否则会造成对象无法释放。
如果要提前释放,使用 DisposeOf 。像下面直接设置为 nil 只是减少引用计数,如果没有其它引用,会直接释放对象,但如果有其它引用存在,就不会释放。所以,在使用 FreeAndNil 时,一定要注意这一点,在移动平台,FreeAndNil 等价于赋值为 NIL。

class procedure TMySimpleClass.SetNil;
var
  MyObj: TMySimpleClass;
begin
  MyObj := TMySimpleClass.Create;
  MyObj.DoSomething (False); // True => raise
  MyObj := nil;
  // do something else
end;
1
2
3
4
5
6
7
8
9
class procedure TMySimpleClass.SetNil;
var
  MyObj: TMySimpleClass;
begin
  MyObj := TMySimpleClass.Create;
  MyObj.DoSomething (False); // True => raise
  MyObj := nil;
  // do something else
end;
Free 方法依然可以被调用,只不过它在自动引用计数模式下,被编译器优化为 X:=nil 。
综上述,要直接立即释放一个对象,那么在自动引用计数模式上,调用 DisposeOf ,调用 Free 或 FreeAndNil 不能保证这一点。

【注意】
1、DisposeOf 是将对象置于一种特殊的“僵尸”状态,其析构函数被调用,但对象本身占用的内存空间并没有被立即回收,其占用的内存只有在其引用计数被清为 0 时才会直接的释放。

2、Delphi 的对象的引用计数最大为 230  次,有一位被用做标志是否已经调用了 DisposseOf。

3、Weak 注解不适合用于大量对象引用的场合,它虽然不会增加引用计数,但会调用内部的 RegisterWeakRef 和 UnregisterRef 函数来处理弱引用信息。这些额外的代码在创建大量对象时,它对效率的影响还是让人有点纠结的。对于这种场合,推荐用 Unsafe 注解来代替 Weak(虽然官方不太推荐)。无论是 Weak 还是 Unsafe,在使用时都要比较小心,以避免内存泄露。Unsafe 与 Weak 的的不同在于 weak 引用的对象释放时,相应的引用会被置为 NIL,而 unsafe 是不管这点事的,这也就解释了为啥 weak 注解会引发 RegisterWeakRef / UnregisterRef 调用了。

4、如果你不希望你的对象被自动管理引用计数,可以重新实现 IInterface 接口的 __AddRef 和 __Release 方法,就象 TComponent 做的那样。

来源:http://blog.qdac.cc/?p=4833

相关阅读 >>

Delphi memo控件对粘贴板的支持

Delphi读写utf-8、unicode格式文本文件

Delphi中adoquery执行错误的捕捉

dephi获取系统常量

Delphi application.processmessages的作用

Delphi 时间转换为gmt格式

Delphi 实现窗口与任务栏右下角对齐

Delphi repeat 递增/递减输出

Delphi的常用条件编译指令

Delphi 无边框窗体常见问题

更多相关阅读请进入《Delphi》频道 >>



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...