【问题标题】:Delphi: Pass by reference or pass by value?Delphi:按引用传递还是按值传递?
【发布时间】:2011-04-20 05:28:40
【问题描述】:

在 Delphi 中,如果我有一个简单的类 myClass,并且我将它的一个实例传递给带有 myFunction( myClass ) 的函数,该函数由 function myFunction( myObject : myClass ) : Boolean 定义...

  • 是否会制作 myObject 的副本?

  • 当我在myFunction中调用myObject的方法时,原来的对象也会受到影响和修改吗?

【问题讨论】:

    标签: delphi parameter-passing


    【解决方案1】:

    对象通过引用传递。不会制作副本;将只有一个类的实例,只有一个对象。原来的对象就是一切。

    【讨论】:

    • 该死的你打败了我... :) +1
    • 是的,原始对象就是堆上的所有内容。但是你确实得到了参考的副本,除非你通过参考传递。在这种情况下,您将获得对对象引用的引用。
    • 函数呢,它们是通过引用传递的吗?我看到有人使用@myProc 作为函数参数。
    【解决方案2】:

    对象通过引用传递。

    【讨论】:

    • 只是一个附录:当您使用 VAR 传递字符串时,字符串也是通过引用传递的
    【解决方案3】:

    除了“对象通过引用传递”之外,还有更多内容。对象是引用类型,因此默认情况下它们总是通过引用传递。任何对象变量都是对象引用。

    但是,如果您“通过引用”传递对象变量(传递给 var 参数),那么如果您在传递给它的例程中将对象替换为不同的对象,您将一旦例程返回,最终会得到一个不同的对象。这样做时要小心;如果更改对某个对象的唯一引用,可能会导致内存泄漏。

    【讨论】:

    • 当您说“将对象替换为不同的对象”时,您的真正意思是“将对象 reference 替换为 reference to目的。”你不能用另一个对象替换一个对象,但你可以覆盖任何你想要的引用。
    • 和@Rob,从某种意义上说,在将“对象”称为引用TObject 的变量时存在如此普遍的误称,MyForm.Width...MyForm.Width 是其引用由 MyForm 变量保存的 Form 的实际宽度。您更改了MyForm 变量,MyForm.Width 是另一个表单的宽度。所以,“你最终会得到一个不同的对象”在一定程度上描述了程序员在实践中的现实。
    【解决方案4】:

    在 Delphi 中,对象是特殊的指针,它指向堆内存上的数据结构。当您将对象传递给函数时,您实际上是在传递指针,而不是整个对象数据的副本。在这种情况下,当您通过该引用修改字段或属性时,它将影响原始对象数据。这是一个演示此行为的简单示例:

    program ObjParamTest;
    
    type
      TMyClass = class
      private
        FMyField : Integer;
      public
        property MyField : Integer read FMyField write FMyField;
      end;
    
    
    function ModifyObject(AnObj: TMyClass);
    begin
      AnObj.MyField := AnObj.MyField + 1;
    end;  
    
    var
      MyObj : TMyClass;
    begin
      MyObj := TMyClass.Create;
      try
        AnObj.MyField := 2;
        Writeln(AnObj.MyField); // ==> Prints 2
        ModifyObject(MyObj);
        Writeln(AnObj.MyField); // ==> Prints 3
      finally
        MyObj.Free;
      end;
    end.
    

    还要注意,参数修饰符(例如 Var、Const、Out)只改变对象引用传递给函数的方式,对原始数据结构没有影响。

    也许这篇文章为您更清楚地了解了在 Delphi 中将参数传递给函数的不同方式:

    Different function parameter modifiers in Delphi(存档版)

    【讨论】:

    • 我同意 Mick 的观点,您的文章非常值得一读。尽管如此,我认为在发送到您的帖子之前在此处发布一个简短、直接的问题答案是最有益的。特别是因为它没有详细说明按值传递对象或通过 var 传递对象之间的区别。
    • 谢谢,我在帖子中添加了一个简短的描述和一个简单的示例。
    • +1。虽然所有答案在技术上都是正确的,但我相信这是对 OP 最有帮助的答案。
    • AnObj在主体中应改为MyObj
    猜你喜欢
    • 1970-01-01
    • 2016-11-28
    • 2017-11-14
    相关资源
    最近更新 更多