【问题标题】:TList of const interface pointersconst 接口指针的 TList
【发布时间】:2021-12-13 01:11:25
【问题描述】:

我有类字段

someList : TList<SomeInterFace>;

我只需要在列表中存储对象并搜索它们,从不想修改。所以我决定写

someList : TList<const SomeInterFace>;

但是我有很多编译器错误。似乎不可能将 const 对象存储在标准的 Delphi 容器中?

【问题讨论】:

  • 您永远不想修改...列表的内容或对象的内容?接口引用的生命周期也是通过引用计数来处理的。 const 仅在作为参数传递时适用于接口引用,并且它用作向编译器发出的信号,不会触发该参数的引用计数机制。您是否尝试在列表中存储弱接口引用?

标签: object delphi interface constants containers


【解决方案1】:

const 仅在方法的上下文中才有意义:

procedure DoSomethingWithInterface(const AInterface: SomeInterface)
begin
  // do something
end;

这里,如果没有const 声明,接口的引用计数在传递给方法时会增加,并在方法返回时再次减少。使用const,接口通过引用传递,但引用计数未修改。这是有效的,因为当您仍在方法中时,接口的引用计数不会下降,因此程序可以将方法中的这种临时使用视为没有发生,从而节省了必须修改的开销引用计数字段。更多关于here的阅读。

然而,将引用存储在列表中是完全不同的事情,因为列表中对象的生命周期是不确定的。方法具有明确的开始和结束,因此您保留对对象的引用的持续时间受到严格限制 - 不存在删除对象的风险(尽管对共享变量进行跨线程操作或其他此类并发错误),而你还在用它。但是,在列表中,无法保证该引用将在列表中存在多长时间,因此您无法绕过增加引用计数。

此外,在方法中使用const 的最大节省是编译器会在方法周围生成一个隐式try/finally 块,以管理引用计数。在方法中使用const 可以节省该try/finally 的开销,这是主要的性能提升。但是,在将字符串或接口引用添加到列表时,不会生成这样的隐式代码,因为开发人员完全可以控制列表中引用的生命周期,这与传递给方法的参数不同, 编译器必须管理。

因此,总而言之,没有办法按照您的建议去做,但也没有需要按照您的建议去做。如果您为列表中的接口引用绕过了引用计数,那么它们所指向的对象可能会在其他对它们的引用消失时被删除,并且您最终会在列表中得到一个死引用。

【讨论】:

  • Remy 是对的:字符串使用“写时复制”(COW)语义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多