Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Records mit := übergeben; ->aktualisierung?


alias5000 - Mo 17.10.05 20:07
Titel: Records mit := übergeben; ->aktualisierung?
Hi
ne grundlegende Frage.
Ich habe in meinem Programm ein Array mit den Records TBeispiel. Also (da dynamisch):

Delphi-Quelltext
1:
BspRecord : array of TBeispiel;                    


Wenn ich nun in einer Prozedur, damit ich weniger schreiben muss folgendes deklariere:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
Procedur XY;
var Bsp: TBeispiel;
begin
...
Bsp := BspRecord[2]; //die 2 ist nicht relevant, es wird eine passende Zahl verwendet
bsp.blablabla := true;  
... //Bsp wird in seinen Eigenschaften verändert, z.B. s.o.
...
end;

So wie ich mir das denke wird Bsp zu einem eigenen Record, und somit werden die Änderungen nicht mehr in BspRecord[2] übernommen.
Um dies zu tun müsste ich am Ende der Prozedur noch schreiben:

Delphi-Quelltext
1:
BspRecord[2] := Bsp;                    


Sehe ich das richtig?


BenBE - Mo 17.10.05 20:13

Ja, das siehst Du richtig.

Es gibt aber noch eine elegantere Lösung:


Delphi-Quelltext
1:
2:
var
    Bla: ^TBeispiel;


Wodurch Bla ein Zeiger wird und dann Bla := @Beispiele[Index]; zur Zuweisung deines Records (der Referenz auf diesen Record) verwendet werden muss. Delphi löst zwar Pointer in gewissem Maße selber auf; es empfiehlt sich aber der Lesbarkeit halber mit bla^.SomeProp auf den somit referenzierten Record zu verweisen. Die Rückzuweisung (und einiger interner Overhead von Delphi) entfällt dann, weil Änderungen direkt im Array vorgenommen werden.


alzaimar - Mo 17.10.05 20:14

Sehr gut erkannt. Aus diesem Grund verwendet man Zeiger:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
Type
  PBeispiel = ^TBeispiel;

Procedur XY;
var 
  Bsp: PBeispiel;
begin
...
  Bsp := @BspRecord[2]; //die 2 ist nicht relevant, es wird eine passende Zahl verwendet
  bsp^.blablabla := true;  
end;

Jetzt ist BspRecord[2] verändert. Noch besser ist es i.A., kein Array of TBeispiel, sondern ein Array Of PBeispiel zu erzeugen. Dann wird (z.b. bei Sortieroperationen) nicht mehr das gesamte TBeispiel (das ja durchaus einige MB gross sein kann) bewegt, sondern immer nur die Zeiger.

Der "Nachteil" der Zeiger-Variante ist, das Du dich um den Speicher selbst kümmern musst.


alias5000 - Di 25.10.05 13:45

OK, danke erstmal.

Und wie komme ich nun vom PBeispiel wieder zurück auf TBeispiel? Sonst müsste ich alles umschreiben und das wär blöd... dazu kommt noch die Speicherverwaltung.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
//So hier der Beispiel-Code dazu
Procedur XY;
var bsp: TBsp;  //PBsp = ^TBsp;
begin
bsp := Utils.GetBsp; //hier hauts nicht hin. Ich bekomme mit GetBsp als Result ein PBsp
//Und wie krieg ich dieses PBsp wieder auf TBsp? Soll heißen, dass TBsp der Record ist, dessen Adresse mir mit PBsp übergeben wird.


Danke schonmal!
Gruß alias5000


alzaimar - Di 25.10.05 14:36


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
Procedur XY;
var 
  bsp: TBsp;  
  
begin
  bsp := Utils.GetBsp^; // das '^' dereferenziert den Zeiger. 
// Wenn p also eine Addresse ist (und p ist vom Typ PBsp), dann bezeichnet
// p^ das TBsp
...


BattleFrog - Do 27.10.05 09:58
Titel: Re: Records mit := übergeben; ->aktualisierung?
wenn man den zeigerquark nicht will, geht auch


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
Procedur XY;
begin
  ...
  with BspRecord[2do //die 2 ist nicht relevant, es wird eine passende Zahl verwendet
  begin
    blablabla := true;  
    ... //Bsp wird in seinen Eigenschaften verändert, z.B. s.o.
    ...
  end;
end;


alias5000 - Sa 29.10.05 16:39

user profile iconalzaimar hat folgendes geschrieben:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
Procedur XY;
var 
  bsp: TBsp;  
  
begin
  bsp := Utils.GetBsp^; // das '^' dereferenziert den Zeiger. 
// Wenn p also eine Addresse ist (und p ist vom Typ PBsp), dann bezeichnet
// p^ das TBsp
...

Wie ist das dann? Der Übergabeparamter PBsp bezeichnet ja im Ursprung ein BspRecord[x]
Wenn ich nun Bsp := GetBsp^; schreibe, verändere ich dann direkt den BspRecord[x], oder muss ich da dann doch BspRecord[x] := Bsp; schreiben?