明确表示对德尔福的所有权

Explicitly expressing ownership in Delphi

本文关键字:所有权 德尔福 表示      更新时间:2023-10-16

我主要是一名C++程序员,我已经习惯了使用std::unique_ptrstd::shared_ptr等类模板来表达我的对象的所有权。德尔福的标准库中是否有类似的东西?在编写代码时,是否有任何表达对象所有权的最佳实践?

编辑:自从C++11成为标准以来,有两个轻量级的帮助程序类,std::shared_ptrstd::unique_ptr

如果我创建一个类型 std::shared_ptr<int> 的变量,它表示指向具有共享所有权的 int 的指针:在引擎盖下是引用计数,当引用计数达到零时,指针会自动释放。此类型表示一种"共享所有权",其中许多对象在完成资源时分担销毁资源的责任。

相比之下,std::unique_ptr表示单一所有权。当unique_ptr超出范围时,将自动释放资源。std::unique_ptr 无法复制:一次只能有一个对象拥有此资源,并且只有一个对象负责清理该对象。

将这些轻量级类与指向 int 的裸指针进行对比,其中它可以表示共享所有权、唯一所有权,也可以只是对其他地方对象的引用!类型什么也没告诉你。

我的问题是:由于 Delphi 支持保存对对象的引用,是否有任何机制可以明确声明"我是这个对象的唯一所有者,当我完成它时,我将释放它",与"我只是为了与它交互而保留对这个对象的引用,但其他人会清理它"与"我与许多其他对象共享这个对象, 谁最后拥有它,谁就可以清理它。

我知道 Collections.Generics 有不同的集合,例如 TList vs TObjectList ,其中 TObjectList 将释放存储在其中的成员,但 TList 不会。你可以说TObjectList"拥有"它的元素,而TList没有。这是我问题的本质,真的。在设计我自己的类时,有没有办法在语言中直接表达这些类型的所有权问题?或者是否有任何开发人员中常见的最佳实践/命名约定?

我不知道

有任何语言结构可以提供帮助,也不知道任何"标准命名约定"。

但是,很久以前,我采用了以下命名约定,以便更轻松地检查类是否正确清理了它们:

  • 根据标准的德尔菲约定,所有字段名称都以"F"开头。
  • 类具有/承担终身管理责任的对象引用,以"FMy"开头。
  • 接口引用类应该显式释放,通过在析构函数中将引用设置为 nil(为了性能,打破循环依赖关系等)以"FMi"开头

非常粗糙,但它有效,并且在浏览您有一段时间未见过的代码时有很大帮助,以防止那些"等等,该引用不应该被释放还是无效?"搜索。

std::unique_ptr 无法复制:一次只能有一个对象拥有此资源

在德尔菲语言中,没有任何类型或机制可以阻止共享"所有权"。始终可以复制任何参考。(阅读:德尔福中没有任何内容可以让你阻止分配,正如大卫所说的那样。

当unique_ptr超出范围时,将自动释放资源。

在德尔福,这只能通过(或通过)接口来实现。德尔福没有垃圾收集器。

并且只有一个对象负责清理对象。

清理的责任你必须自己执行。或者将该任务委托给(其他)框架。例如,默认的 Delphi VCL 类TComponent实现了自动所有权(和销毁),可以选择与 RemoveComponentInsertComponent 进行交换/控制。

设计我自己的类时,有没有办法在语言中直接表达这些类型的所有权问题?或者是否有任何开发人员中常见的最佳实践/命名约定?

不完全是主题,但肯定相关:有多个"单例"设计模式实现强制执行对象的一次性创建。

关于命名约定:"所有者"(或您自己的示例中的"OwnsObjects")一词明确表示所有权,因为所有者将在必要时负责销毁。因此,使用窗体作为所有者(按钮的默认构造函数的单个参数)创建的按钮不需要手动销毁。

德尔福中的概念在很多情况下与C++不同。这两种语言都是第三代,但Delphi喜欢在比C++更高的抽象层次上工作。例如,Delphi 支持指针,但在引用概念时很少使用指针,这与 C++ 中的

指针概念并不完全相同。

在 Delphi 中,对象变量实际上是引用(或者在较低级别的抽象中,它们是指针)。在C++中,当您声明一个对象变量时,构造函数会立即被调用,而在 Delphi 中则不是,您必须在给定的时刻调用它,这将分配内存并运行构造函数。因此,C++ 和 Delphi 中对象的内存管理受制于不同的生命周期。

说这些只是为了告诉你,德尔福的内存管理设计风格与C++不同。这就是为什么 Delphi 没有任何帮助程序类可以精确地执行您想要的操作。然而,德尔福提供了一个名为Interfaces的概念,这在C++中是不存在的(至少,很久以前我曾经与C++一起工作时,它不存在)。接口类似于抽象类,因为它们没有代码。您必须为接口提供类实现器,该类将提供代码。但是,Interfaces提供参考计数内存管理,我相信,它接近您正在寻找的内容。

所以,我对你的回答是:德尔福在内存管理方面为您提供的最接近的语言结构是接口。所以,我建议你至少研究一下,得出你自己的结论。