Delphi对象创建与释放

本文深入探讨了Delphi中组件对象的创建与释放机制,包括组件对象与非组件对象的区别,重点解析了组件对象的构造与析构过程,以及如何正确管理对象生命周期。

前言:做Delphi很多年了,打算留下了啥,所以准备写博客了。

关于对象的创建和释放,相信大家都非常熟悉了,在这里我打算浅谈一下。

本文中我将对象分为2大类,组件对象和非组件对象,暂时不考虑接口以及实现接口的类。

组件对象,也就是从TComponent继承下来的类对象。其它的就归于非组件对象。各位不要太过纠结,给我举反例。

  • 非组件对象

比如Tlist、TCollection等等,此类对象必须手动释放,建议写成try-finally块

比如: try

           L := TList.create;

           ...你的过程

       Finally

           L.free;

       End;

 

  • 组件对象

这是本文的重点,因为组件对象比较特殊。

我们首先关注一下组件对象的构造函数,其在VCL中的原型是:

constructor TComponent.Create(AOwner: TComponent);

begin

  FComponentStyle := [csInheritable];

  if AOwner <> nil then AOwner.InsertComponent(Self);

end;

请注意它有一个参数 AOwner: TComponent

其中执行了一个方法  AOwner.InsertComponent(Self);

VCL中的原型函数是:

procedure TComponent.InsertComponent(AComponent: TComponent);

begin

  AComponent.ValidateContainer(Self);

  ValidateRename(AComponent, '', AComponent.FName);

  Insert(AComponent);

  AComponent.SetReference(True);

  if csDesigning in ComponentState then

    AComponent.SetDesigning(True);

  Notification(AComponent, opInsert);

end;

 

procedure TComponent.Insert(AComponent: TComponent);

begin

  if FComponents = nil then FComponents := TList.Create;

  FComponents.Add(AComponent);

  AComponent.FOwner := Self;

end;

 

FComponents: TList;

这些方法全部是TComponent类的方法,也就是说所有的组件都具有这些方法。通过观察原代码可知:Create方法中,除了创建对象外,它会将当前创建的组件对象加入到AOwner的

FComponents 里面,实际上这个FComponents是一个List,我们可以称呼它为属主。说人话就是:比如btn = Tbutton.Create(Self) --Self是一个form。在这里创建了一个button,创建完毕后,btn的属主就是form,然后btn就加入到了form的FComponents属性

 

接下来观察一下析构函数

destructor TComponent.Destroy;

begin

  Destroying;

  if FFreeNotifies <> nil then

  begin

    while Assigned(FFreeNotifies) and (FFreeNotifies.Count > 0) do

      TComponent(FFreeNotifies[FFreeNotifies.Count - 1]).Notification(Self, opRemove);

    FreeAndNil(FFreeNotifies);

  end;

  DestroyComponents;

  if FOwner <> nil then FOwner.RemoveComponent(Self);

  inherited Destroy;

end;

 

析构函数更加详细的代码,读者可自行查阅VCL.这个析构函数的意思就是:当组件在释放时候,会做一下几件事

  1. 释放自己本身内部的组件,比如form和panel会释放放在里面的组件

2、释放FComponents属性里面的对象

3、如果有属主,通知属主对象,在FComponents里面移除自己

 

当我们知道了原理后,就可以回答一些问题了。

1、比如下列代码,有问题吗?

procedure TForm1.Button1Click(Sender: TObject);

var

  btn : TButton;

begin

  btn := TButton.Create(Self);

  btn.Free;

end;

 

procedure TForm1.Button1Click(Sender: TObject);

var

  btn : TButton;

begin

  btn := TButton.Create(Self);

end;

 

我的回答:都是对的。其原因就是:第一个指定了属主,然后手动释放了,在释放的时候,btn就会通知form,要在FComponents里面移除自己,所以当from释放的时候,它就不会在释放btn;第二个原因就是:指定了属主,不过没有手动释放,这样在form释放自己的时候,它会去释放btn;

 

  1. 补充一下对象生命周期的问题。

对于非模态窗体,就是用show出来的窗体,因为不知道窗体什么时候需要释放,我们可以指定属主,通常是application

而模态窗体,因为它有明确的生命周期,我们知道何时该销毁它,这个时候指定不指定都可以,不过需要在窗体关闭的时候,立刻销毁它。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值