在Delphi中明确表达所有权

时间:2013-09-12 12:43:37

标签: c++ delphi delphi-xe3 ownership-semantics

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

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

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

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

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

我的问题是:由于Delphi支持保持对象的引用,是否有任何机制可以明确说明“我是这个对象的唯一所有者,当我完成它时,我会释放它”,vs“我是只是保持对这个对象的引用以便与它进行交互,但是其他人会清理它“vs”我与许多其他对象共享这个对象,并且最后拥有它的任何人都可以清理它。“

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

3 个答案:

答案 0 :(得分:4)

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

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

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

非常粗糙,但它确实有效,并且在通过您偶尔没有看到的代码时帮助了很多,以防止那些“等待,不应该将该引用释放或填充?”搜索。

答案 1 :(得分:2)

  

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

在Delphi语言中,没有类型或机制阻止共享“所有权”。始终可以提供任何参考的副本。 (阅读:Delphi中没有任何内容允许你阻止分配,正如David很好地说的那样。)

  

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

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

  

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

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

  

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

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

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

答案 2 :(得分:1)

Delphi中的概念在很多场合都与C ++不同。这两种语言都是第三代语言,但Delphi喜欢使用比C ++更高级别的抽象。例如,Delphi支持指针,但是当它们被引用到引用的概念时很少被使用,这与C ++中的概念不完全相同。

在Delphi中,对象变量实际上是引用(或者在较低的抽象级别,它们是指针)。在C ++中,当你声明一个对象变量时,构造函数是imediatly,在Delphi中它不是,你必须在给定的时刻调用它,什么将分配内存并运行构造函数。因此,C ++和Delphi中对象的内存管理是根据不同的生命周期进行的。

所有这些只是告诉你,Delphi中的内存管理设计风格与C ++不同。这就是为什么Delphi没有任何帮助类可以完全按照您的需要进行操作的原因。但是,Delphi提供了一个名为Interfaces的概念,它在C ++中不存在(至少在我以前使用C ++的时候还没有)。接口类似于抽象类,因为它们没有代码。您必须为接口提供类实现器,该类将提供代码。但是,Interfaces提供了引用计数内存管理,我相信它与您正在寻找的内容接近。

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