在下面的代码中,创建了一个TStringList类型的新对象,并将其传递给使用该对象的过程。通过将对象传递给方法 ProcToFillStringList ,可以通过复制引用来创建新的对象引用。我对此代码的疑问是:
参数 SList 中存储的对象引用会发生什么 方法返回后?它是否删除对象的引用 从堆栈?
Free()方法在内部实际上做了什么?它是从堆栈中删除对象的所有引用还是删除它 对象本身?删除了哪些参考文献?
当方法返回时,对象引用(不是对象本身)会自动从堆栈中删除吗?
传递参考byref会不会更好?
var
SL: TStringList; // first object reference
begin
SL := TStringList.Create; // creating object
try
ProcToFillStringList(SL);
finally
SL.Free; // -> what gets 'freed' here? the object? the references? both?
end;
end;
procedure ProcToFillStringList(const SList: TStrings); // second object reference
SList.Add('x'); // not calling Free -> does the reference get removed?
end;
答案 0 :(得分:9)
以下是新版本Delphi上Free
方法的代码:
procedure TObject.Free;
begin
// under ARC, this method isn't actually called since the compiler translates
// the call to be a mere nil assignment to the instance variable, which then calls _InstClear
{$IFNDEF AUTOREFCOUNT}
if Self <> nil then
Destroy;
{$ENDIF}
end;
有两种不同的情况。当编译到具有自动引用计数的环境(即iOS)时,Free根本不起作用,只有在删除对它们的最后一个引用时才释放对象(但是如上面代码的注释中所述,编译器会更改您的{ {1}}到SL.Free
,所以如果它是对象的最后一个引用,它将被释放,SL实际上设置为nil。
但是在所有其他平台中,对象都不是引用计数。当调用Free时,对象内存被释放,但你的变量没有自动设置为nil(不是说另一个指向同一个对象的变量),这样的语法就不可能了。任何对象的方法都不能改变它所调用的变量。这就是您编写SL:=nil
而不是SL := TStringList.Create
的原因。在第一种情况下,您将获得创建对象的新内存地址并为其分配SL。在第二个SL没有被初始化并且可以指向任何地方,所以没有办法在那里创建对象。
所以,回答你的问题:
当超出范围时,将删除本地过程中的对象引用。但是如果使用SL.Create
或const
参数,则不会首先创建它。实际上,您在这里使用相同的参考SL。
在iOS var
中什么都不做,当SL变量超出范围时,对象将被自动销毁。在其他平台上,Free会破坏对象,并且根本不会影响其他引用。
是的,他们这样做。
使用最能描述您情况的修饰符。 Free
将告诉编译器和使用您的代码的人(包括您自己)在程序中不会更改参数,编译器可以通过值(对于小于指针的对象)或通过引用传递它,但无论如何它选择的内容,refcount永远不会增加,所以从这个角度来看,你可以认为你使用完全相同的对象,就像通过引用传递一样。
使用Const
(通过引用)您可能会意外地更改传递给过程的变量,这会使您的意图不清楚,因此只有在您真的想要更改此变量时才使用它,否则使用Var
。
答案 1 :(得分:1)
在embarcadero的文档中写了
如果对象引用不是nil
,则System :: TObject :: Free会自动调用析构函数
在您的情况下,意味着在您调用SL.Free的位置清除对象SL。从TObject继承的对象不知道该实例有多少引用。只有指向SL实例地址的指针才会传递给函数调用ProcToFillStringList。该实例未被告知新的参考。
如果要处理引用计数,请查看TInterfacedObject和3方法
public void foo {
label.setVisible(true);
//the label is not visible
foo2();
//here the label is visible
}
答案 2 :(得分:0)
通过复制参考
创建新的对象引用
新引用const SList
只是指向对象的不可更改指针。如果它存在于堆栈中,它将从堆栈中删除(在这种情况下,参数通过寄存器传递)。
Free
并未清除任何引用。它只是破坏了一个物体,释放了它的记忆。有&#39; FreeAndNil&#39;解除对象并使一个引用 nil
的例程。其他参考文献仍然存在。