您的位置:首页 > 编程语言 > Delphi

Delphi 中的自动释放策略

2017-01-31 15:45 162 查看
来自万一老师的博客:http://www.cnblogs.com/del/archive/2011/12/21/2295794.html

--------------------------------------------------------------------------------------------------

一、指定 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;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: