2009-09-08 8 views
5

Voglio creare un gruppo di record (RWell) e memorizzarli in un array in un determinato ordine. Quindi voglio creare un nuovo array (layout diverso) e riorganizzare i record al suo interno. Ovviamente, non voglio duplicare i dati nella RAM, quindi penso che nel secondo array dovrei mettere i puntatori ai record del primo array. Tuttavia, non posso farlo. Qualcuno può dire cosa c'è di sbagliato con il codice qui sotto? GrazieMatrice di (puntatori a un record)

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; 

Risolto da Rob K.

+1

Avrete commenti sulla vostra tecnica per l'aggiunta alla fine dell'array dinamico. Può essere inefficiente e può frammentare la memoria. Faresti meglio a fare in modo che la matrice abbia le dimensioni necessarie solo una volta e quindi assegnare i valori al prossimo elemento non assegnato man mano che procedi. Un'altra opzione è usare un 'TList', che è molto bravo a memorizzare i puntatori. A partire da Delphi 2009, potrebbe anche essere sicuro come "TList ". –

+0

Non conosco la dimensione di quell'array in fase di esecuzione. E so che non è ottimale, ho fissato la sua lunghezza. Ma è molto piccolo (sotto le 600 voci), quindi la frammentazione sarà minima. Non mi preoccuperò di cambiarlo ora. Grazie per il suggerimento :) – Ampere

+0

Sono d'accordo che è meglio usare un elenco qui. –

risposta

6

Nella funzione AddWell, si sta passando il record per valore. Ciò significa che la funzione ottiene copia del parametro attuale. Stai memorizzando un puntatore al parametro formale, che è probabilmente solo una posizione sulla pila locale della funzione.

Se si desidera un puntatore a un pozzo, poi passare un puntatore a un pozzo:

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

Un'altra opzione è quella di superare il record valore const. Per i record, questo significa che il parametro attuale viene passato come riferimento. Un puntatore al parametro formale è anche un puntatore al parametro attuale:

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

Tuttavia, non mi baserei molto su questo. Quando vuoi dei puntatori, passa i puntatori. Alcune persone cercano di evitare i riferimenti nel loro codice, ma non hanno nulla da temere.

+1

Non è garantito che AFAIK const imponga il passaggio per riferimento, quindi non ci farei affidamento qui. –

+0

Prima non ha funzionato: tipi incompatibili PWell e RWell. Il secondo ha funzionato, MA all'interno di quella procedura ho il codice che ha bisogno di modificare AWell, che ora è di sola lettura (const). (mi dispiace, non ho fornito il codice completo per rendere la mia domanda facile da leggere/capire). – Ampere

+0

Il primo non ha funzionato perché non è stato modificato il * chiamante *. È necessario passare un puntatore quando si chiama la funzione: 'AddWell (@WellMX [2, 3])'. –

Problemi correlati