2009-06-19 46 views
2

下面,我插入了Ray Konopka編寫的代碼(Coderage演示文稿的一部分)。我打算使用它,但是,我不確定如何清理(即時)多個對象。 我所有的嘗試都是不安全的,並導致內存泄漏。 任何想法表示讚賞。 謝謝,在delphi中釋放多個對象

program stringlistDictionary; 

{$APPTYPE CONSOLE} 

uses 
Classes, 
SysUtils; 

type 
    TPlayer = class 
    public 
    Name: string; 
    Position: string; 
    Hits: Integer; 
    AtBats: Integer; 
    constructor Create(Name, Position: string); 
end; 


    constructor TPlayer.Create(Name, Position: string); 
    begin 
     inherited Create; 
     Self.Name := Name; 
     Self.Position := Position; 
     Hits := 0; 
     AtBats := 0; 
    end; 


    var 
     Team: TStringList; 
     Player, NewPlayer: TPlayer; 
     I: Integer; 


    function FindPlayer(const Name: string): TPlayer; 
    var 
     Idx: Integer; 
    begin 
     Result := nil; 
     if Team.Find(Name, Idx) then 
     Result := TPlayer(Team.Objects[ Idx ]); 
    end; 


    begin {== Main ==} 

     Writeln('StringList Dictionary'); 
     Writeln('---------------------'); 
     Writeln; 

     Team := TStringList.Create; 
     try 
     NewPlayer := TPlayer.Create('Aramis Ramerez', 'Third Base'); 
     NewPlayer.Hits := 120; 
     NewPlayer.AtBats := 350; 

     Team.AddObject(NewPlayer.Name, NewPlayer); 

     NewPlayer := TPlayer.Create('Derrick Lee', 'First Base'); 
     NewPlayer.Hits := 143; 
     NewPlayer.AtBats := 329; 

     Team.AddObject(NewPlayer.Name, NewPlayer); 

     NewPlayer := TPlayer.Create('Ryan Theriot', 'Short Stop'); 
     NewPlayer.Hits := 87; 
     NewPlayer.AtBats := 203; 

     Team.AddObject(NewPlayer.Name, NewPlayer); 

     Player := FindPlayer('Derrick Lee'); 
     if Player <> nil then 
      Writeln('Player Found: ', Player.Name, ', ', Player.Position) 
     else 
      Writeln('Player not found.'); 
     Writeln; 

     Writeln('Active Roster'); 
     Writeln('-------------'); 

     for I := 0 to Team.Count - 1 do 
      Writeln(TPlayer(Team.Objects[ I ]).Name, #9, 
        TPlayer(Team.Objects[ I ]).Position); 

     Readln; 

     finally 
     //!! Need to free the players. 
     Team.Free; 
     end; 

    end. 
+0

其他說明:Self.Name等在構造函數是不必要的。爲何使用控制檯應用程序?爲什麼不把一個單獨的課程用於玩家名單? – 2009-06-19 21:12:09

+0

如果這是整個應用程序,你*不需要釋放任何內存,因爲無論如何你已經完成應用程序 – BlackTigerX 2009-06-19 21:13:09

+0

@BlackTigerX:這看起來像一個簡單的例子。對於這種情況,你是對的,但是他試圖使用它的真實代碼可能要複雜得多。 – 2009-06-19 22:22:08

回答

13

德爾福2009年,TStringList中構造有一個可選的布爾參數 「OwnsObjects」。如果將其設置爲true,則會自動釋放這些對象。

否則,你可以做到以下幾點:

for i := Team.Count-1 downto 0 do begin 
    Team.Objects.Free; 
end; 
Team.Free; 

順便說一句,公共領域都望而卻步。您可以使用屬性,以便您可以控制對字段可以訪問哪些內容。你可以添加setter函數來驗證輸入。

type 
    TPlayer = class 
    private 
    FName  : string; 
    FPosition : string; 
    FHits  : Integer; 
    FAtBats : Integer; 
    public 
    constructor Create(const AName, APosition: string); 

    property Name: string read FName; 
    property Position: string read FPosition; 
    property Hits: Integer read FHits write FHits; 
    property AtBats: Integer read FAtBats write FAtBats; 
end; 
3

只是澄清gamecat回答:我不知道德爾福2009年,但通常的對象屬性需要一個指標,你並不真的需要一個逆循環,所以:

for i := 0 to Team.Count-1 do 
    Team.Objects[i].Free; 
Team.Free; 

或:

while Team.Count > 0 do 
begin 
    Team.Objects[0].Free; 
    Team.Delete(0); 
end; 
Team.Free; 
4

還挺明顯的,但還是 - 你不必想清除的TStringList對象每次寫「爲...免費」的代碼。你可以把它放到一個全局函數中。

procedure FreeObjects(sl: TStringList); 
var 
    i: integer; 
begin 
    for i := 0 to sl.Count - 1 do 
    sl.Objects[i].Free; 
end; 

FreeObjects(Team); 

或者你可以把它放到TStringList助手中。

TStringListHelper = class helper for TStringList 
public 
    procedure FreeObjects; 
end; 

procedure TStringListHelper.FreeObjects; 
var 
    i: integer; 
begin 
    for i := 0 to Count - 1 do 
    Objects[i].Free; 
end; 

Team.FreeObjects; 
2

使用D7,我可以繼承TStingList