Einzelnen Beitrag anzeigen

Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.106 Beiträge
 
Delphi 11 Alexandria
 
#8

Re: Wie eigenen Record definieren und verwenden?

  Alt 15. Jan 2008, 18:57
Moin Tony,

Zitat von TonyMontana:
Hatte ich wohl überlesen in der Delphi Hilfe, dass man für Felder, die Instanzen von Klassen sind Speicher reservieren muss...
Ich fürchte, ich muss Deine Verwirrung erst noch einmal etwas steigern.

Die Felder sind keine Instanzen von Klassen, sondern können Zeiger auf Instanzen von Klassen enthalten.
Das mit dem Zeiger ist jetzt nicht der Knackpunkt, da dies eh der normale Weg ist auf Instanzen zuzugreifen.
Wichtiger ist, dass man nicht den Speicher für die Felder, sondern für die Instanzen der Klassen reservieren muss.
Man kann diesen Feldern ja schliesslich auch die Adressen von Instanzen zuweisen, die man auch noch ganz woanders erzeugt, und gespeichert hat.

Ein Beispiel:
Ich habe eine TObjectList, in der ich eine Reihe von Objekten gespeichert habe.
Nun möchte ich diese gerne in einer Liste ausgeben.
Um den Zugriff zu erleichtern übergebe ich nun jedes Objekt, der Reihe nach, an eine Variable des gespeicherten Typs, und kann dann mit dieser arbeiten, ohne, dass ich hierfür noch einmal extra Speicher reservieren muss:

Delphi-Quellcode:
TMyEntry = class(TObject)
private
  FsTitel : string
  FsInhalt : string;
public
  property Titel : string read FsTitel write FsTitel;
  property Name : string read FsName write FsName;
end;

TMyList = class(TObjecList)
end;

// Fml soll hier ein Feld vom Typ TMyList sein
// lv soll hier ein TListView sein

var
  me : TMyEntry;
  i : integer;
  li : TListItem;

begin
  for i := 0 to ml.Count-1 do begin
    li := lv.Items.Add;
    // Es wird kein Speicher reserviert, da dies schon früher passiert ist
    // und die Adresse ist in der Objektliste gespeichert
    me := ml[i] as TMyEntry;
    li.Caption := me.Titel;
    li.SubItems.Add(me.Name);
  end;
end;
Zitat von TonyMontana:
Aber dann ist doch das Feld an sich nicht _unzulässig_, sondern erfordert nur eine Speicherreservierung, die man selbst vornehmen muss, oder? Immerhin wird es ja kompiliert.
Das Feld selber ist ja auch völlig OK, nur enthält es nichts sinnvolles, aber das interessiert den Compiler nicht

Zitat von TonyMontana:
Ist noch alles etwas undurchsichtig für mich, wann ich Speicher reservieren muss und wann das Delphi selbst erledigt, gerade auch bei Strings und so...
Ganz genau genommen, reservierst Du auch bei Strings den Speicher selber, nur fällt das nicht so auf, wie bei Objekten.
Wenn Du, z.B., aus einem TFileStream lesen willst, so kannst Du hierfür einen String nehmen:

Delphi-Quellcode:
var
  fs : TFileStream;
  sBuf : string;

begin
  fs := TFileStream.Create('Pfad zur Datei',fmOpenRead);
  try
    // Und hier knallt es, weil eben kein Speicher für den String reserviert wurde.
    fs.Read(sBuf[1],fs.Size);
    // was man so lösen kann:
    SetLength(sBuf,fs.Size);
    fs.Read(sBuf[1],fs.Size);
  finally
    fs.Free;
  end;
end;
Grundsätzlich kannst Du sagen:
Wenn Du mit einem Zeiger arbeiten willst, muss der vorher etwas sinnvolles enthalten.
Objekte sind, auch wenn die Compilermagic das verschleiert, nichts weiter als Zeiger.

(Es gibt Ausnahmen, da es Funktionen gibt, die die Speicherreservierung selbständig machen, aber das ist dann bei denen auch meist dokumentiert, da man, i.d.R., den Speicher dann trotzdem selber freigeben muss.)

Zitat von TonyMontana:
Kann mir jemand verraten, wo man das -verständlich- nachlesen kann? Ich finde die Delphi Hilfe nicht immer optimal muss ich sagen...
Ich hoffe es ist verständlicher geworden, wenn nicht, frag' einfach noch mal nach.

Zitat von TonyMontana:
Das Erste am besten im OnCreate Ereignis des Formulars und das Zweite wohl am besten im OnDestroy Ereignis des Formulars, oder?
Das wäre eine gute Position.
Für die Stelle an der man ein Objekt instanziert, bzw. wieder freigibt, gibt es allerdings kein Patentrezept.
Grundsätzlich sollte man es so spät wie möglich erzeugen, und so früh wie möglich wieder freigeben.
(das gilt für alle Resourcen, z.b. auch Handles)
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat