Einzelnen Beitrag anzeigen

norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
504 Beiträge
 
Delphi 12 Athens
 
#5

AW: TObjectList sauber an function übergeben und wieder zurück

  Alt 10. Jul 2020, 07:33
Zunächst Danke für die schnellen Antworten
Das stimmt so nicht. Das Objekt (genauer: die Instanz) selbst wird ohne Angabe von const, var oder out als Call by Value übergeben.
Dass Objekte kein var brauchen dachte ich anfangs auch habe aber eben festgestellt, dass es unterschiedlich reagiert.
Um es sicher zu stellen:
  • Wenn das Objekt in der Funktion erzeugt wird, muss ein var dazu
  • Wenn man verhindern will, dass eine neue Instanz erzeugt wird (Create), kann man das mit const verhindern

Ich würde aber in Routinen ohne triftigen Grund keine Instanzen erzeugen, da man sonst sehr schnell durcheinanderkommt und sich entweder Speicherlecks oder wilde Zeiger fabriziert.
Dem stimme ich zu. Grund dafür hier mal anzufragen. Um Sicherheit zu gewinnen

[edit] Mist, zu langsam [/edit]
Das verunsichert mich etwas. Deine Vorredner haben doch was anderes gezeigt. Nämlich wie die Instanzen in der Routine erzeugt werden.

Diese Konstruktion produziert ein Memoryleak, weil DestList durch den Aufrufer nicht freigegeben werden kann. Denn die Referenz der neu erzeugten Liste wird so nicht an den Aufrufer zurückgegeben.
Das hatte ich festgestellt. Jetzt weiß ich warum.

Letzte Frage:
Könnte Aufbau lTempList := DoAdding(DestList) Vorteile bieten? Was muss da beachtet werden bzw. stimmt das hier?
Delphi-Quellcode:
function PrePareList(SourceList: TTestList): TTestList;
// ------------------------------------------------------------------------------------------
// Erstellt Liste und kopiert Werte von SourceList dort hin
var
  i: Integer;
  lTest: TTest;
begin
  Result.Clear;

  for i := 0 to SourceList.Count - 1 do
  begin
    lTest := TTest.Create;
    Result.Add(lTest);
    lTest.Value := SourceList[i].Value;
  end;
end;

function DoAddition(SourceList: TTestList): TTestList;
// ------------------------------------------------------------------------------------------
// Führe rechenfunktion durch, die auch auf vorige Werte in der Liste zurückgreift.
// Wenn SourceList und Result auf selbem Objekt liegen, wurden die vorigen Werte durch den Loop schon verändert => Zuerst zusätzliche Instanz schaffen. Oder gibt es andere Möglichkeit?
var
  i: Integer;
  lTest: TTest;
  lTempList:TTestList;
begin
  lTempList := lTempList.Create(true);
  lTempList := PrePareList(SourceList);


  for i := 0 to SourceList.Count - 1 do
  begin
    if i>0 then
      Result.Value := lTempList[i].Value + lTempList[i-1].Value
    else
      Result.Value := lTempList[i].Value;
  end;

  lTempList.Free;
end;

Procedure Start;
// ------------------------------------------------------------------------------------------
// Vorbereitung der Liste und Aufruf der Funktionen
var
  lStartList, lResultList:TTestList;
begin
  lStartList := TTestList.Create(true);
  lResultList := TTestList.Create(true);

  ...

  lResultList := PrePareList(SourceList);
  
  // Und hier mein Problem. Da die Berechnungen aufeinander aufbauen sollen, ist Result-Objekt = Übergabe-Objekt. Wenn jeder Eintrag für sich geändert wird kein Problem.
  // Wenn die Funktion aber auf vorige Einträge zugreift, wären die schon verändert. Jetzt müsste ich in der Funktion zuerst eine Kopie erzeugen. Korrekt?

  lResultList := DoAddition(lResultList);

  ...

  lStartList.Free;
  lResultList := TTestList.Create(true);
  Mit Zitat antworten Zitat