8

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

编辑:由于 C++11 成为标准,有两个轻量级帮助类,std::shared_ptrstd::unique_ptr.

如果我创建一个 type 的变量std::shared_ptr<int>,它代表一个指向具有共享所有权的 int 的指针:在底层是引用计数的,当引用计数达到零时,指针会自动释放。这种类型表达了一种“共享所有权”,其中许多对象在使用完资源后共同承担销毁资源的责任。

相反,std::unique_ptr表示单一所有权。当 unique_ptr 超出范围时,资源会自动释放。std::unique_ptr 不能被复制:一次只能有一个对象拥有该资源,并且只有一个对象负责清理该对象。

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

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

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

4

3 回答 3

4

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

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

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

非常粗糙,但它很有效,并且在处理您一段时间未见过的代码时帮助很大,以防止出现“等等,该引用不应该被释放或取消吗?” 搜索。

于 2013-09-12T18:07:56.057 回答
2

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

在 Delphi 语言中,没有阻止共享“所有权”的类型或机制。可以随时制作任何参考的副本。(阅读:Delphi 中没有任何东西可以阻止分配,正如David所说的那样。)

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

在 Delphi 中,这只能通过(或通过)接口实现。Delphi 没有垃圾收集器。

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

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

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

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

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

于 2013-09-12T18:01:05.243 回答
1

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

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

这一切只是为了告诉你,Delphi 中的内存管理设计风格与 C++ 不同。这就是为什么 Delphi 没有任何帮助类来精确地做你想要的。然而,Delphi 提供了一个名为 的概念Interfaces,它在 C++ 中不存在(至少,在很久以前我使用 C++ 时它没有)。接口在没有代码的意义上类似于抽象类。您必须为接口提供类实现器,并且该类将提供代码。但是,Interfaces提供一个引用计数内存管理,我相信它与您正在寻找的内容接近。

因此,我对您的回答是:Delphi 在内存管理方面为您提供的可用于您目的的最接近的语言结构是Interfaces。因此,我建议您至少研究一下以得出自己的结论。

于 2013-09-12T18:50:39.967 回答