2009-09-08 7 views
5

Je veux créer un groupe d'enregistrements (RWell) et les stocker dans un tableau dans un certain ordre. Ensuite, je veux créer un nouveau tableau (disposition différente) et réorganiser les enregistrements en elle. Bien sûr, je ne veux pas dupliquer des données dans la RAM, donc je pense que dans le second tableau, je devrais mettre des pointeurs sur les enregistrements dans le premier tableau. Cependant, je ne peux pas faire ça. Quelqu'un peut-il dire ce qui ne va pas avec le code ci-dessous? MerciTableau de (pointeurs vers un enregistrement)

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; 

par Rob K. Solved

+1

Vous allez recevoir des commentaires sur votre technique d'ajout à la fin du tableau dynamique. Il peut être inefficace et peut fragmenter la mémoire. Vous feriez mieux de ne faire qu'une seule fois le tableau dont vous aurez besoin, puis d'assigner des valeurs à l'élément non assigné suivant. Une autre option consiste à utiliser un 'TList', ce qui est très bien pour stocker des pointeurs. À partir de Delphi 2009, il pourrait même être de type sécurité comme 'TList '. –

+0

Je ne connais pas la taille de ce tableau à l'exécution. Et je sais que ce n'est pas optimal quand je règle sa longueur. Mais c'est très petit (moins de 600 entrées) donc la fragmentation sera mineure. Je ne vais pas déranger le changer maintenant. Merci pour la suggestion :) – Ampere

+0

Je serais d'accord qu'il est préférable d'utiliser une liste ici. –

Répondre

6

Dans votre fonction AddWell, vous passez le record en valeur. Cela signifie que la fonction obtient une copie du paramètre réel. Vous stockez un pointeur sur le paramètre formel, qui est probablement juste un emplacement sur la pile locale de la fonction.

Si vous voulez un pointeur vers un puits, puis passer un pointeur vers un puits:

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

Une autre option est de passer par l'enregistrement valeur const. Pour les enregistrements, cela signifie que le paramètre réel est passé en référence. Un pointeur sur le paramètre formel est un pointeur sur le paramètre réel:

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

Je ne vraiment compter sur cela, cependant. Quand vous voulez des pointeurs, passez des pointeurs. Certaines personnes essaient d'éviter les pointeurs dans leur code, mais ils n'ont rien à craindre.

+1

AFAIK const n'est pas garanti pour imposer le passage par référence, donc je ne compterais pas ici. –

+0

Le premier n'a pas fonctionné: Types incompatibles PWell et RWell. Le second a fonctionné MAIS dans cette procédure j'ai du code qui doit modifier AWell, qui est maintenant en lecture seule (const). (désolé, je n'ai pas fourni le code complet pour rendre ma question facile à lire/comprendre). – Ampere

+0

Le premier n'a pas fonctionné parce que vous n'avez pas changé le * appelant *. Vous devez passer un pointeur lorsque vous appelez la fonction: 'AddWell (@WellMX [2, 3])'. –

Questions connexes