2009-06-19 8 views
2

以下、Ray Konopka(Coderageプレゼンテーションの一部)で書かれたコードを挿入しました。私はそれを使用するつもりですが、私は複数のオブジェクトを(その場で)きれいにする方法がわかりません。 私のすべての試みは不合理で、メモリリークがレンダリングされました。 ご意見をいただければ幸いです。 おかげで、Delphi 2009にして複数のオブジェクトを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

その他の発言をサブクラス化することができます。コンソールアプリケーションを使用する理由なぜ選手のリストのための別のクラスを使用しないでください? –

+0

これは、あなたがアプリケーションをやっているので、メモリを解放する必要がないアプリケーション全体であれば、とにかくアプリケーションが完了しているからです。 – BlackTigerX

+0

@BlackTigerX:これは簡単な図のようです。この場合、あなたは正しいですが、彼がこれを使用しようとしている実際のコードはおそらくもっと複雑です。 –

答えて

13

、TStringListのコンストラクタは、オプションのブール・パラメータ "OwnsObjects" を持っています。これをtrueに設定すると、オブジェクトは自動的に解放されます。

エルス

あなたは次の操作を行うことができます:

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

ところで、パブリックフィールドが推奨されています。あなたはプロパティを使用するので、フィールドへのアクセスを制御できます。また、入力を検証するためにセッター関数を追加することもできます。

gamecatの答えについてちょうど明確化
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; 
+0

ありがとうございます。 私のアプリケーションであなたのソリューションをテストし、すべてのオブジェクトが破壊されました。 本当にありがとうございます。 – Greener

+0

この回答を修正したい。 おそらく、D2009が新しいコンストラクタを導入したのでしょうか、それとも、少なくともOwnsObjectsプロパティがDelphi 4(おそらくは16ビットDelphi 1から)から存在し、作成後に簡単にオン/オフできるようになりました。 http://www.freepascal。org/docs-html/rtl/classes/tstringlist.ownsobjects.html –

3

:私は、Delphi 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; 
+0

"Team.Delete(0);"ステートメントが必要ですか? – Argalatyr

+0

彼はそれが書かれている方法、はい。 –

+0

@Mason:あなたは大丈夫です - 私は通常それをそうしません。 – Argalatyr

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ヘルパーに入れることができます。 Self.Nameなどコンストラクタで必要とされない:D7を使用して

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; 
+0

IIRCでは、クラスヘルパーはコンパイラの警告なしでも簡単に壊れることがあります。 – mjn

+1

はい、クラスヘルパーは問題があります。あるクラスに対して複数のヘルパーがある場合、最後のヘルパーは常に他のすべてのクラスを上書きします。それでも、彼らは便利です。 – gabr

+0

@ Gabr:便利なコード例をありがとう。私はクラスヘルパーがこの方法で使用できることを知らなかった。 – Greener

2

、私はちょうどTStingList

+0

うまくいけば、あなたはほとんどすべてのオブジェクト指向言語でこれを行うことができます...しかし、STLについて考える...多分そうではない – jpfollenius

関連する問題