zoukankan      html  css  js  c++  java
  • Delphi 中的自动释放策略-转

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

    一、指定 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;
  • 相关阅读:
    面向对象的程序设计-2-创建对象
    面向对象的程序设计-1-理解对象
    react组件的生命周期
    react-router 组件式配置与对象式配置小区别
    mobx @computed的解读
    十分钟介绍mobx与react
    less学习
    git-简单流程(学习笔记)
    几种视频编码器的编译及使用方法
    一位程序员工作10年总结的13个忠告
  • 原文地址:https://www.cnblogs.com/rogge7/p/6078396.html
Copyright © 2011-2022 走看看