Tworzenie nowym obiektów w free pascalu i dodawanie do listy

0

Siema !

Mam sobie TListe któe przechowuje wskaźniki. Chciałbym tam dodać wskaźnik na rekord który sam zdefiniowałem np. TMyRecord. Problem w tym, że nie mam pojęcia jak utworzyć nowyą instację recordu. W C++ napisałbym :

MyList.Add(new TMyRecord());

Próbowałem analogicznie w FP ( pod lazarusem) z .Create, jednak pokazuje mi, że nie mam zdefiniowanego konstruktora - i nie chce mieć bo to zwykła struktura a nie klasa i nie chcę rozbudowywać w klase. Prosze o podpowiedz jak to zrobić ew. gdzie szukać. Znalazłem rozwiązanie - zbudować swoją własną klase reprezentującą liste dziedziczącą po TList, jednak nie chce mi się wierzyć, że w FreePascalu wszystko trzeba budować od podstaw i nie ma podomnej funkcjonalnosci. Proszę o pomoc, ew. wskazówkę.

0

np. tak deklarujesz sobie rekord

PMyRecord = ^TMyRecord;
TMyRecord = record
  foo: string;
  bar: integer;
end;

wykorzystanie:

var
  PtrMyRecord: PMyRecord;
begin
  New(PtrMyRecord);  //przydzieleanie pamięci rekordowi

  PtrMyRecord^.foo := 'test';
  PtrMyRecord^.bar := 99;

  Dispose(PtrMyRecord); //zwalnianie pamięci 
0

To rozumiem, że po zwolnieniu pamięci obiekt się niszczy. Jak dodam go do TListy i zniszcze obszar pamięci pod wskaźnikiem to w TList tez już nic nie będzie bo wskaźnik wskazuje na ten sam obszar pamięci. W takim razie powinienem dodać nowy record do listy a potem wynulować wskaźnik ? W zasadzie ciekaw jestem, czy można pominąć wskaźnik i wykorzystać samo new... nic zaraz zrobie eksperyment.

0

zgadza się jak użyjesz dispose to rekord będzie zwolniony ale wskaźnik będzie dalej "wisiał", po zwolnieniu możesz sobie przypisać nil, ale to kosmetyka. Po stworzeniu rekordu i dodaniu do listy przez MyList.Add(PtrMyRecord); będziesz miał skaźnik na niego zapamiętany w liście i to w niej później przed usunięciem elementu musisz zwolnić pamięć mniej więcej w ten sposób:
Dispose(PMyRecord(MyList.Item[5])); rzutowanie na PMyRecord jest ważne bo wkazujesz w ten sposób ile pamięci zwolnić (TList nie ma pojęcia o typie wskaźnika)

0

A nie jest tak, że jak nie przypisze nil do wskaźnika to gdy do niego sięgnę, żeby, np. sprawdzić czy nie jest nilowy to nie wysypie się program bo sięgnę do nieprzydielonego mi obszaru pamięci ?

Mniej wiecej wiem o co chodzi ale mam problem ze swoim kodem. Kod jest mniej więcej taki :

type
   PricingPosition = record
      nazwa: AnsiString;
      grupa: AnsiString;
      cenaMin: Currency;
      cenaMax: Currency;
    end;

   p_PricingPosition = ^PricingPosition;

...

function TBrowseVendors.Parse(ToParse: AnsiString): TList;
var
  substring, subcell: AnsiString;
  I, J, p: integer;
  Positions: TList;
  pPos : p_PricingPosition;
const
  HeaderTag = '<tr class="tabela_cennik_naglowek">';
  PositionTag = '<tr class="tabela_cennik_pole">';
  EndOfColTag = '</td>';
begin 

Positions := TList.Create;

  for I := 1 to Length(ToParse) do
  begin
    substring := substring + ToParse[I];
    if Pos(PositionTag, substring) > 0 then
    begin
      Delete(substring, Length(substring) - 36, 36);
      if Pos(HeaderTag, substring) = 0 then
      begin
        p := 0;
        for J := 1 to Length(substring) do
        begin
          subcell := subcell + substring[J];
          New(pPos);
          if Pos(EndOfColTag,subcell) > 0 then
          begin
            Trim(subcell);
            Delete(subcell,1,4);
            Delete(subcell,Length(subcell) - 4,5);
            case p of
              0 : pPos^.nazwa := subcell;
              1 : pPos^.grupa := subcell;
              2 : pPos^.cenaMin := Currency(subcell);
              3 : pPos^.cenaMax := Currency(subcell);
            end;
            subcell := '' ;
            inc(p);
          end;
          Positions.Add(pPos);
          pPos := nil;
        end;
          subcell := '' ;
      end;
      substring := '';
    end;
  end;
   For I:=0 to Positions.Count do
  begin
    ShowMessage(p_PricingPosition(Positions[i])^.nazwa );
  end;
end;

Problem w tym, że jak ostatnią pętlą chodzę bo kolekcji i ją wyrzucam MessageBoxem to nic tam nie ma albo są śmieci - co robię źle ??

0

spróbuj ShowMessage(p_PricingPosition(Positions.Items[i])^.nazwa ); a co do 1 pytania to zgadza się, to dobra praktyka, ale tutaj w sumie różnicy nie robi.

0

Niestety chyba nie masz racji do końca. Twój kod nie działał tak jak
chciałem. Po debugu okazało się, że w zły sposób ładuje dane do recordu a
potem recordy do listy. Poprawiłem i twój kod zaczął działać, ale co
lepsze mój stary również :

ShowMessage(p_PricingPosition(LPos[I])^.nazwa);

Znaczy to tyle, że

p_PricingPosition(LPos[I])^

jest równoważne z

p_PricingPosition(LPos.Items[I])^

Może mi ktos wytłumaczyć po co w tej strukturze taka redundancja?

poprawienie błędnego formatowania kodu - fp

1 użytkowników online, w tym zalogowanych: 0, gości: 1