2009-09-08 15 views
5

Chcę utworzyć grupę rekordów (RWell) i przechowywać je w tablicy w określonej kolejności. Następnie chcę utworzyć nową tablicę (inny układ) i zamienić w nią rekordy. Oczywiście nie chcę duplikować danych w pamięci RAM, więc w drugiej tablicy powinienem umieścić wskaźniki do rekordów w pierwszej tablicy. Jednak nie mogę tego zrobić. Ktoś może powiedzieć, co jest nie tak z poniższym kodem? DziękiTablica (wskaźniki do rekordu)

Type 
    RWell= record         
    x: string; 
    i: integer; 
    end; 

    PWell= ^RWell; 

    RWellArray= Array[0..12, 0..8] of RWell;  


procedure TClass1.CreateWells 
var 
    WellMX: RWellArray; 
begin 
    { should I initialize the WellXM here? } 
    { note: WellXM is a static array! } 

    other stuff 
end; 



var Wells: array of PWell; 
procedure TClass2.AddWell(aWell: RWell); 
begin 
aWell.Stuff:= stuff; {aWell cannot be readonly because I need to change it here} 

SetLength(Wells, Length(Wells)+ 1); { reserve memory } 
Wells[High(Wells)]:= @aWell; 
end; 



procedure TClass3.DisplayWell; 
var CurWell: RWell; 
begin 
CurWell:= CurPrimer.Wells[iCurWell]^;  <--- AV here (but in debugger the address is correct) 
end; 

rozwiązany przez Rob K.

+1

Otrzymasz komentarze na temat swojej techniki dołączania do końca tablicy dynamicznej. Może być nieefektywna i może dzielić pamięć. Lepiej przygotuj tablicę, której potrzebujesz, tylko raz, a następnie przypisz wartości do następnego nieprzypisanego elementu. Inną opcją jest użycie 'TList', który jest bardzo dobry w przechowywaniu wskaźników. Począwszy od Delphi 2009, może być nawet bezpieczny dla typów jako "TList ". –

+0

Nie wiem, rozmiar tej tablicy w czasie wykonywania. I wiem, że to nie jest optymalne. Ustawiłem jego długość. Ale jest bardzo mały (poniżej 600 wpisów), więc fragmentacja będzie niewielka. Nie będę tego zmieniać teraz. Dzięki za sugestię :) – Ampere

+0

Zgodziłbym się, że lepiej jest użyć listy tutaj. –

Odpowiedz

6

W funkcji AddWell, jesteś przejazdem rekord wartością. Oznacza to, że funkcja otrzymuje kopię aktualnego parametru. Przechowujesz wskaźnik do formalnego parametru, który jest prawdopodobnie po prostu lokacją na lokalnym stosie funkcji.

Jeśli chcesz wskaźnik do studni, a następnie przekazać wskaźnik do studni:

procedure AddWell(AWell: PWell); 
begin 
    SetLength(Wells, Length(Wells) + 1); 
    Wells[High(Wells)] := AWell; 
end; 

Innym rozwiązaniem jest przekazanie rekordu przez wartości const. W przypadku rekordów oznacza to, że rzeczywisty parametr jest przekazywany jako odniesienie. Wskaźnik do formalnego parametru jest również wskaźnikiem do faktycznego parametru:

procedure AddWell(const AWell: RWell); 
begin 
    SetLength(Wells, Length(Wells) + 1); 
    Wells[High(Wells)] := @AWell; 
end; 

Nie chciałbym jednak na tym polegać. Kiedy chcesz wskaźników, podaj wskaźniki. Niektórzy próbują unikać wskazówek w swoim kodzie, ale nie mają się czego obawiać.

+1

Nie można zagwarantować, że AFAIK const wymusi przekazanie przez odniesienie, więc nie będę tutaj polegał. –

+0

Pierwsza nie zadziałała: Niezgodne typy PWell i RWell. Drugi działał, ALE w tej procedurze mam kod, który musi zmodyfikować AWell, który teraz jest tylko do odczytu (const). (przepraszam, nie podałem pełnego kodu, aby moje pytanie było łatwe do odczytania/zrozumienia). – Ampere

+0

Pierwsza z nich nie działała, ponieważ nie zmieniłeś * wywołującego *. Podczas wywoływania funkcji musisz podać wskaźnik: 'AddWell (@WellMX [2, 3])'. –