文档章节

Delphi 中的自动释放策略

涂孟超
 涂孟超
发布于 2014/09/26 15:33
字数 875
阅读 6
收藏 0

一、指定 Owner 后, 随 Owner 连带释放:

//uses Vcl.StdCtrls, Vcl.ExtCtrls;

var
  panel: TPanel;

procedure TForm1.Button1Click(Sender: TObject);
begin
  panel := TPanel.Create(Self);
  panel.Parent := Self;

  with TButton.Create(panel) do //AOwner = panel
  begin
    Parent := panel;
    Caption := 'New Button';
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if Assigned(panel) then
    FreeAndNil(panel); //连带释放以它为 Owner 的对象
end;


二、使用接口:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

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

  //
  IBass = Interface
    function GetName: string;
    procedure SetName(const AName: string);
    property Name: string read GetName write SetName;
  end;

  //
  TBass = class(TInterfacedObject, IBass)
  private
    FName: string;
  protected
    function GetName: string;
    procedure SetName(const AName: string);
  public
    constructor Create(const AName: string);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  X: IBass;
begin
  X := TBass.Create('WanYi');
  ShowMessage(X.Name);
  X.Name := '万一';
  ShowMessage(X.Name);
  {X 在此自动释放}
end;

{ TBass }

constructor TBass.Create(const AName: string);
begin
  FName := AName;
end;

function TBass.GetName: string;
begin
  Result := FName;
end;

procedure TBass.SetName(const AName: string);
begin
  FName := AName;
end;

end.


三、使用结构:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

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

  //
  TBass = record
  private
    FName: string;
    procedure SetName(const AName: string);
  public
    constructor Create(const AName: string);
    property Name: string read FName write SetName;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  X: TBass;
begin
  X := TBass.Create('WanYi');
  ShowMessage(X.Name);
  X.Name := '万一';
  ShowMessage(X.Name);
  {X 在此自动释放}
end;

{ TBass }

constructor TBass.Create(const AName: string);
begin
  FName := AName;
end;

procedure TBass.SetName(const AName: string);
begin
  FName := AName;
end;

end.


四、在 initialization 中建立、在 finalization 中释放:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

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

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  List: TStringList;

procedure TForm1.Button1Click(Sender: TObject);
begin
  List.Clear;
  List.Add('WanYi');
  ShowMessage(List.Text);
end;

initialization
  List := TStringList.Create;
finalization
  List.Free;

end.


五、使用动态数组而不是 TList、TStringList 等:

procedure TForm1.Button1Click(Sender: TObject);
var
  arr: Array of string;
  i: Integer;
  s: string;
begin
  for i := 0 to 6 do
  begin
    SetLength(arr, Length(arr)+1);
    arr[High(arr)] := StringOfChar(Char(i+65), 3);
  end;
  for s in arr do ShowMessage(s);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  arr: TArray<string>;
  i: Integer;
  s: string;
begin
  for i := 0 to 6 do
  begin
    SetLength(arr, Length(arr)+1);
    arr[High(arr)] := StringOfChar(Char(i+65), 3);
  end;
  for s in arr do ShowMessage(s);
end;


六、使用 TObjectList 而不是 TList:

uses System.Contnrs;

procedure TForm1.Button1Click(Sender: TObject);
var
  list: TObjectList;
  i: Integer;
  btn: TButton;
begin
  list := TObjectList.Create;
  for i := 0 to 6 do
  begin
    btn := TButton.Create(Self);
    with btn do begin
      Caption := Format('Btn %d', [i+1]);
      Parent := Self;
      Top := Height * i;
      Left := Width * i div 2;
    end;
    list.Add(btn);
  end;
  ShowMessage('TObjectList 释放时, 会同时释放其中的对象');
  list.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  list: TList;
  i: Integer;
  btn: TButton;
begin
  list := TList.Create;
  for i := 0 to 6 do
  begin
    btn := TButton.Create(Self);
    with btn do begin
      Caption := Format('Btn %d', [i+1]);
      Parent := Self;
      Top := Height * i;
      Left := Width * i div 2;
    end;
    list.Add(btn);
  end;
  ShowMessage('TList 释放后, 其中的对象并未释放');
  list.Free;
end;


七、使用 TObjectList<T> 而不是 TList<T>:

uses System.Generics.Collections;

procedure TForm1.Button1Click(Sender: TObject);
var
  list: TObjectList<TButton>;
  i: Integer;
  btn: TButton;
begin
  list := TObjectList<TButton>.Create;
  for i := 0 to 6 do
  begin
    btn := TButton.Create(Self);
    with btn do begin
      Caption := Format('Btn %d', [i+1]);
      Parent := Self;
      Top := Height * i;
      Left := Width * i div 2;
    end;
    list.Add(btn);
  end;
  ShowMessage('TObjectList 释放时, 会同时释放其中的对象');
  list.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  list: TList<TButton>;
  i: Integer;
  btn: TButton;
begin
  list := TList<TButton>.Create;
  for i := 0 to 6 do
  begin
    btn := TButton.Create(Self);
    with btn do begin
      Caption := Format('Btn %d', [i+1]);
      Parent := Self;
      Top := Height * i;
      Left := Width * i div 2;
    end;
    list.Add(btn);
  end;
  ShowMessage('TList 释放后, 其中的对象并未释放');
  list.Free;
end;


八、使用结构体而不是结构体指针:

{假如某个函数的参数需要一个结构指针}
function Area(rect: PRect): Integer;
begin
  Result := rect.Width * rect.Height;
//  Result := rect^.Width * rect^.Height;
end;

{直接声明指针并分配空间后需手动释放}
procedure TForm1.Button1Click(Sender: TObject);
var
  P: PRect;
begin
  New(P);
  P^ := Rect(10, 10, 60, 50);
  ShowMessage(IntToStr(Area(P))); //2000
  Dispose(P);
end;

{}
procedure TForm1.Button2Click(Sender: TObject);
var
  R: TRect;
begin
  R := Rect(10, 10, 60, 50);
  ShowMessage(IntToStr(Area(@R))); //2000
end;

本文转载自:http://www.cnblogs.com/del/archive/2011/12/21/2295794.html

涂孟超
粉丝 12
博文 2011
码字总数 14107
作品 0
深圳
程序员
私信 提问
具体的知识 && 知识在项目中的应用(以指针和内存的知识引出)

Delphi有两种创建对象的方法 直接创建对象实体 比如创建一个线程有下面这样两种方式 用变量(指针)保存对象实体地址 说明 第一种方式就是创建了一个线程,这个线程去执行,但是你却没有这个线...

xumenger
09/29
0
0
Delphi利用数据库实现文件打包

以下代码出自http://blog.csdn.net/hellogv/,引用请注明出处! Delphi利用数据库实现文件打包的基本思路分析: 【1】在Delphi中,把文件读取为文件流,再以流的形式保存在数据库的OLE 对象的...

晨曦之光
2012/03/14
216
0
delphi pchar char byte string转换问题

delphi pchar char byte string转换问题 注:Delphi中的Char,PChar,PByte,Byte,String的相互转换,您是不是也遇到过,为此头疼过吗?你要是明白了他们的原理就会轻松了。 话题064840的标题是...

鹅倌
2017/01/06
0
0
Delphi、PChar和Char数组的比较

Delphi、PChar和Char数组的比较   string和Char数组都是一块内存, 其中存放连续的字符. string保存具体字符的内存对用户是透明的, 由Delphi管理它的分配, 复制和释放, 用户不能干预(其实也...

技术小甜
2017/11/08
0
0
Delphi中使用汇编(关于POS函数的问题)

在delphi中使用汇编异常的简单,只用使用关键字asm ....end来引导就行了。 得到一个字符在字符串中的位置有很多方法,最简单的就是使用delphi自己的Pos函数 另外一个方法就是使用 循环查找字...

技术小美
2017/11/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

PostgreSQL 11.3 locking

rudi
今天
5
0
Mybatis Plus sql注入器

一、继承AbstractMethod /** * @author beth * @data 2019-10-23 20:39 */public class DeleteAllMethod extends AbstractMethod { @Override public MappedStatement injectMap......

一个yuanbeth
今天
11
1
一次写shell脚本的经历记录——特殊字符惹的祸

本文首发于微信公众号“我的小碗汤”,扫码文末二维码即可关注,欢迎一起交流! redis在容器化的过程中,涉及到纵向扩pod实例cpu、内存以及redis实例的maxmemory值,statefulset管理的pod需要...

码农实战
今天
4
0
为什么阿里巴巴Java开发手册中不建议在循环体中使用+进行字符串拼接?

之前在阅读《阿里巴巴Java开发手册》时,发现有一条是关于循环体中字符串拼接的建议,具体内容如下: 那么我们首先来用例子来看看在循环体中用 + 或者用 StringBuilder 进行字符串拼接的效率...

武培轩
今天
9
0
队列-链式(c/c++实现)

队列是在线性表功能稍作修改形成的,在生活中排队是不能插队的吧,先排队先得到对待,慢来得排在最后面,这样来就形成了”先进先出“的队列。作用就是通过伟大的程序员来实现算法解决现实生活...

白客C
今天
81
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部