Delphi:为什么TStringlist不能在程序中分配?
第一个程序:
procedure TestOne(List : TStringList); var TempList : TStringList; begin TempList := TStringList.Create; TempList.Add('Test'); List := TempList; TempList.Free; end; procedure TForm1.Button1Click(Sender : TObject); var aList : TStringList; begin aList := TStringList.Create; TestOne(aList); Memo1.Lines := aList; end; 当我单击按钮时,备忘录不显示任何内容,并且断点显示该过程不执行此行: List := TempList; 我修改了程序: procedure TestTwo(List : TStringList); var TempList : TStringList; begin TempList := TStringList.Create; TempList.Add('Test'); List.Text := TempList.Text; //or List.Assign(TempList); //List := TempList; TempList.Free; end; 这次它有效. 那么为什么它不能使用List:= TempList; ? 解决方法
当您按值传递变量时,Delphi会在堆栈中复制参数值,并且在该方法内对该参数所做的所有更改都将通过该副本完成.
这是帕斯卡自Turbo Pascal时代开始以来的方式,也许从一开始就是这样.考虑一下: procedure TestInt(Int: Integer); begin Int := 10; Writeln(Int); //writes 10 end; var I: Integer; begin I := 5; Wirteln(I); //writes 5 TestInt(I); Writeln(I); //also writes 5 end. 现在,当您将对象作为参数传递时,您必须记住对象变量是对对象的引用(指向对象实际存储在堆中的地址的指针).但是,如果通过引用传递参数,则上述规则仍然适用:引用的副本在堆栈中生成.您在方法/过程中对该引用所做的任何更改都是通过该副本完成的. 行List:= TempList;仅更改引用,使其指向不同内存位置中的不同对象.当过程返回时,该值将丢失,与TestInt过程返回时整数值丢失的方式相同. 从不执行该行的事实是优化器的实际应用.由于从未使用过新值,优化器会从最终的exe中删除赋值,并且该行实际上从未执行过. 您可以更改参数声明以通过引用传递它(var参数),但在处理对象时这不是一个好主意,因为您必须考虑谁负责释放对象的内存以避免内存泄漏. 你没有告诉你要完成什么,但看起来像是分配方式,因为赋值将字符串从一个列表复制到另一个列表.您必须考虑直接在List上工作而不使用TempList,如下所示: procedure TestOne(List : TStringList); begin List.Clear; List.Add('Test'); end; procedure TForm1.Button1Click(Sender : TObject); var aList : TStringList; begin aList := TStringList.Create; TestOne(aList); Memo1.Lines := aList; end; 如您所见,结果是相同的. 编辑 Rob在评论中指出了一些重要内容,因此我将解释为什么Button1Click方法的最后一行有效:Memo1.Lines:= aList; 这看起来像是直接分配,但你必须知道你在处理Delphi property.
查看如何声明TCustomMemo的Lines属性: TCustomMemo = class(TCustomEdit) .. .. property Lines: TStrings read FLines write SetLines; 这意味着,当您为属性赋值时,您实际上正在调用SetLines方法,将Value作为参数传递,如下所示: Memo1.SetLines(AList); SetLines实现如下所示: procedure TCustomMemo.SetLines(Value: TStrings); begin FLines.Assign(Value); end; 因此,您最终发出了相同的TStrings.Assign调用,它将源列表中的所有字符串复制到目标列表. 这是Delphi处理对象属性并保持对对象的明确所有权的方法.每个组件都创建并拥有它自己的子对象,并创建和拥有对象. 对属性的赋值运算符(:=)是sintactic糖,允许组件编写者在读取或写入值时引入副作用,并允许程序员认为该属性是标准字段并享受舒适那副作用. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |