我有一个帮助程序类,可以在整个应用程序中广泛使用。实现依赖于接口引用计数,这个想法大致是:
...
var
lHelper: IMyHelper;
begin
lHelper := TMyHelper.Create(some params);
...some code that doesn't have to access lHelper
end;
因此,实现依赖于IMyHelper在方法结束时超出范围,但不是之前。
所以我要问的是,在未来的某些Delphi编译器中,如果在其余的方法中没有访问该变量,那么Delphi编译器在创建之后会立即释放界面吗?
答案 0 :(得分:10)
见this comment from Barry Kelly(来自Embarcadero):
关于你之前的评论,关于显式变量:在我们优化接口变量使用的假设(和破坏变化)情况下,我们不仅可能破坏所描述的类似RAII的功能,而且还可以破坏显式变量方法;不使用分配给FooNotifier和BarNotifier的值,因此“理论上”它们可以更快地释放,甚至可能重用相同的存储。
但是,当然,界面的破坏可能会产生副作用,而这正是帖子中效果所依赖的。改变语言使得像这样的副作用有明显的变化,这不是我们自愿做的事情。
因此您可以猜测Embarcadero不会在此处引入任何向后兼容性更改。重用接口内存的好处不值得打破兼容性并引入副作用:保存指针(4或8字节)现在不值得,特别是当堆栈已经分配和对齐时(x64模型使用)堆栈多于x86)。
只有在语言中引入了垃圾收集器(从我个人的角度来看,我不想要这样),对象的生命周期才会发生变化。但在这种情况下,生命时间可能会更长。
在所有情况下,您都可以创建自己的代码,以确保它将在方法结束时发布:
var
lHelper: IMyHelper;
begin
lHelper := TMyHelper.Create(some params);
try
...some code that doesn't have to access lHelper
finally
lHelper := nil; // release the interface count by yourself
end;
end;
实际上,这是编译器已经生成的代码。写这个将是完全多余的,但它将确保编译器不会欺骗你。
在谈到接口和引用计数时,请考虑Delphi中循环引用的潜在问题。有关接口循环引用的“弱指针”的需要,请参阅this great article (i.e. "Example 2-15")。
其他语言(如Java或C#)使用垃圾收集器来解决此问题。 Objective C使用明确的“归零弱指针”机制来解决它 - 请参阅this discussion或this SO answer for a potential implementation。也许Delphi的未来版本可能会考虑使用类似于Objective C中引入的ARC模型的实现。但我怀疑会有一个明确的语法来保持与现有代码的兼容性。
答案 1 :(得分:4)
documentation说明了这一点(强调我的):
在Win32平台上,接口引用通常通过引用计数来管理,这取决于从System / IInterface继承的_AddRef和_Release方法。使用引用计数的默认实现,当只通过接口引用对象时,不需要手动销毁它;当对象的最后一次引用超出范围时,会自动销毁该对象。
局部变量的范围是方法,因此当前规范是在方法完成之前不会调用_Release
。
我们从未承诺将来不会更改规范,但我认为对这部分语言进行更改的可能性非常小。