Mam tobretki z kilkoma elementami. Muszę zastąpić jedną z nich z jednym nowym na tym samym przedmiocie (bez zmiany liczby). Robię następujące czynności:

procedure TForm1.Button1Click(Sender: TObject);
var
  TObj: TObjectList;
  LPoint: TPPoint;
  i: integer;
begin
  TObj:= TObjectList.Create;
  try

    for i:= 0 to 3 do
    begin
        LPoint:= TPPoint.Create(i, i+ 1);
      TObj.Add(LPoint);
    end;

    LPoint:= TPPoint.Create(21, 22);
    TObj.Items[1]:= nil;
    TObj.Items[1]:= LPoint;

    for i:= 0 to 3 do
    begin
        ShowMessage(IntToStr(TPPoint(TObj.Items[i]).X));
    end;

  finally
    TObj.Free;
  end;
end;

Moje pytanie brzmi: jak mogę uwolnić wymieniany element pamięci? Pomoc mówi "Objekt zostanie uwolniony, jeśli jego indeks zostanie ponownie przypisany". Czy polecenie jest wystarczająco poleceń {{x0}?

Z góry dziękuję za wszelkie informacje.

2
genakust 17 luty 2017, 11:42

2 odpowiedzi

Najlepsza odpowiedź
TObj.Items[1]:= nil;
TObj.Items[1]:= LPoint;

Tutaj wykonujesz dwa zadania, więc klasa próbuje uwolnić dwa przedmioty.

TObj.Items[1]:= nil;

W tym momencie poprzednia pozycja jest non-nil referencją dodaną w swojej wcześniejszej pętli. Ten obiekt jest zatem zniszczony.

TObj.Items[1]:= LPoint;

Gdy ta linia wykonuje, TObj.Items[1] = nil, a więc metoda Free jest wywoływana nil. Nic się nie dzieje.

Dolna linia polega na tym, że kod jest przeładowany. Możesz zastąpić.

TObj.Items[1]:= nil;
TObj.Items[1]:= LPoint;

Z

TObj.Items[1]:= LPoint;

Klasa zniszczy obiekt aktualnie zapisany w TObj.Items[1], a następnie wymień go za pomocą LPoint. Tak jak chcesz.

3
David Heffernan 17 luty 2017, 09:40

TOBECCECTLICE.Create () dba o swoje produkty Management Management, po utworzeniu z własnością = true (domyślne zachowanie)

Testowałem go za pomocą Delphi Xe7, więc nie mogę zagwarantować, że jest to dokładnie takie samo zachowanie w Delphi 7. Na przykład deklarowanie TOBJ: TOBECTLICE bez określonego typu jest niemożliwe (nie sporządza).

Użyłem Tlabel zamiast TPpoint i przemianowałem zmienne, aby było mniej mylące. Aby upewnić się, że został uwolniony, dodałem raportmemoryleaksonshutdown: = true do mojego DPR. Zdecydowanie musi mieć pewność, że nie zadzierasz z pamięcią. Niestety pojawił się w Delphi 2006, więc nie jest dostępny w Delphi 7.

Ten kod zastępuje element na liście bez żadnych wycieków pamięci:

procedure TForm3.Button1Click(Sender: TObject);
var
  list: TObjectList<TLabel>;
  listItem: TLabel;
  i: integer;
begin
  list:= TObjectList<TLabel>.Create();
  try

    for i:= 0 to 3 do
    begin
        listItem:= TLabel.Create(nil);
        listItem.Caption := 'list item ' + IntToStr(I);
        list.Add(listItem);
    end;

    listItem:= TLabel.Create(nil);               
    listItem.Caption := 'list item replaced';
    list.Items[1]:= listItem;

    for i:= 0 to 3 do
    begin
        ShowMessage(list.Items[i].Caption);
    end;
  finally
    list.Free;
  end;
end;
1
Etsitpab Nioliv 17 luty 2017, 09:42