如何通过引用/指针释放和nil一个未知的对象实例?

时间:2015-08-12 12:19:02

标签: delphi delphi-7

我有一个装有单个控件的容器。此控件可以是少数几种类型之一(TMyFrame后代)。控件正在运行时创建和销毁。

在某些时候我需要释放 nil这个控件:

var
  C: TControl;

  C := SomeForm.MyContainer.Controls[0];
  C.Free;
  C := nil;

但问题是控件实例本身未设置为nil。

这可能吗?

我想关键点是一个实例可以有很多引用它。我刚刚意识到一个引用不能"看到"所有其他未知参考文献。

2 个答案:

答案 0 :(得分:2)

无法填充对象实例,在这种情况下,不需要将任何引用设置为nil

如果Container.Controls[0]有效,则Container是控件的父级。当您释放该控件时,VCL负责从父级中提取已离去的子项,因此在您释放Container.Controls[0]后,ControlCount将为0Container.Controls[0]将无效

答案 1 :(得分:2)

<强>更新

根据您的评论,在动态创建控件时,您不会存储对控件的引用。在这种情况下,您无需将任何内容设置为nil

VCL框架本身包含对控件的各种引用。但这些都是由框架管理的。你提到 ActiveControl。如果销毁活动控件,则框架负责管理ActiveControl属性。

除了破坏控件之外,你无需做任何事情。 不需要清除参考,因为没有参考。

有一种机制可以自动设置对nil的引用。它在TComponent中实施。在TComponent的析构函数中,调用了SetReference(False)并且实现了这样的实现:

procedure TComponent.SetReference(Enable: Boolean);
var
  Field: ^TComponent;
begin
  if (FOwner <> nil) then
  begin
    Field := FOwner.FieldAddress(FName);
    if Field <> nil then
      if Enable then Field^ := Self else Field^ := nil;
  end;
end;

所以,假设你有一个这样的表格:

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  end;

这两个按钮是由表单流框架创建的。假设在Button2Click中你写Button1.Free。然后,对SetReference的调用会将Button1变量设置为nil

现在,您正在讨论在运行时创建的控件。您没有告诉我们您如何定义未设置为nil的引用。如果您想安排引用自动设置为nil,则需要执行以下操作:

  1. 将引用声明为控件的Owner
  2. 的已发布字段
  3. 确保控件的Name与您在步骤1中声明的已发布字段相同。
  4. 如果你不能这样做,那么你需要手动编写代码来设置对nil的引用。这样做:

    SomeReference := nil;
    

    现在,我不知道你将如何掌握SomeReference。只有你能知道。因为只有您知道要将此引用设置为nil的位置。

    或者整个问题可能是一个完全的误解。也许您没有对动态创建的控件的引用。在这种情况下,使用Controls[]或其他方法找到控件,调用Free,然后完成作业。