Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Pointer auf Record oder Record als lokale Variable?


Tranx - Mo 11.02.13 22:20
Titel: Pointer auf Record oder Record als lokale Variable?
Hallo,

ich habe mal wieder eine Frage: Was ist Euer Meinung nach besser? Als lokale Variable den Record selber zu nehmen, oder einen POointer auf diesen? Beispiel:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
Typ
  pRec = ^Rec;
  Rec = record
   Var1 , Var2 : extended;
        end;



// entweder:
function TueWas(const Wert1, Wert2 : extended) : extended;
var
  LokalRec : Rec;
begin
  LokalRec.Var1 := Wert1;
  LokalRec.Var2 := Wert2; 
  Result := LokalRec.Var1 * LokalRec.Var2;
end;  

// oder:
function TueWasAnderes(const Wert1, Wert2 : extended) : extended;
var
  pLokalRec : pRec;
begin
  pLokalRec^.Var1 := Wert1;
  pLokalRec^.Var2 := Wert2; 
  Result := pLokalRec^.Var1 * pLokalRec^.Var2;
end;


Oder gibt es da keine Unterschiede? Bei einem habe ich schon etwas entdeckt, und das ist, wenn z.B. der Typ Rec in einer Class auftaucht, als Variable:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
type
  pRec = ^Rec;
  Rec = record
          Var1 , Var2 : extended;
        end;

:
 TD = Class(TList);
       RecVar : Rec;
      end
 TForm  = Class(TForm);
             function TueWas(const Wert1, Wert2 : extended) : extended;
          end;

var
  Daten : TD;
  Form : TForm;


Dann funktioniert z.B.


Delphi-Quelltext
1:
  Daten.RecVar.Var1 := Wert1 // in der Funktion Tuewas nicht.                    


Fehler: Der linken Seite kann nichts zugewiesen werden. Erst die Überführung in eine lokale Variable des Typs Rec löst dann das Problem:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
function TForm.TueWas(const Wert1, Wert2 : extended) : extended;
var
 LokalRec : Rec;
begin
 LokalRec := Daten.RecVar;
 LokalRec.Var1 := Wert1;
 LokalRec.Var2 := Wert2;
 Result := LokalRec.Var1 * LokalRec.Var2;
end;


Ich hoffe, ich habe das Ganze einleuchtend dargestellt. Ich habe in meinen Programmen oft Listen mit komplexen Strukturen (u.a. Analysenergebnisse (Konzentrationen, Elemente, Sollwerte, Vergleiche, Korrekturflags ....) und daher habe ich häufig solche Mehrfachreferenzierungen. Ich habe festgestellt, dass - die Daten stammen aus Datenbanken - das einmalige Erzeugen solch einer Liste und die nachfolgenden Operationen an dieser Liste und das abschließende Speichern der geänderten Daten in die Datenbank sehr viel schneller ablaufen als dauernd in der Datenbank "herumzuwühlen". Wie gesagt, Analysenergebnisse (z.B. Stahl mit 26 Elementen pro Analyse, 1-25 verschiedene Proben pro Auftrag und dazu noch Vergleichsproben. Da lohnt es sich schon, die Daten zu übertragen. Ich rede hier von 10 Sekunden statt 10 Minuten Abarbeitungszeit (z.B. für Korrelationsanalysen, Vergleiche mit Sollwerkstoffen, Veränderungen von Nachkommastellen und erneute Vergleiche ....). Das nur zum Hintergrund meines Anliegens.

Danke schon mal für Anmerkungen, Hinweise und Tips.

Gunther


jaenicke - Mo 11.02.13 22:43

Deine Funktion TueWasAnderes ist so nicht korrekt, denn du benutzt einen nicht initialisierten Pointer. Wenn du einen Pointer auf einen Record verwendest, musst du den auch immer erst mit New initialisieren, damit der Speicher überhaupt reserviert und der Pointer darauf zugewiesen ist.

Die Zuweisung in einer Property funktioniert nicht als direkter Wert innerhalb des Records, da der Record beim Abrufen der Property kopiert wird. Damit arbeitest du nur auf einer temporären Kopie, würdest die Änderungen also nicht in den echten Record schreiben. Das erkennt der Compiler, da du das sicher nicht meintest.

Das ist auch der Hintergrund dessen, dass ein Pointer auf einen Record oft schneller in der Benutzung ist:
Da wird nur der Pointer kopiert, aber wenn du hingegen direkt den Record nutzt, stets der gesamte Recordinhalt.

Statt mit Pointern auf Records herumzuhantieren würde ich dir allerdings eher zu Klassen und Objekten raten. Die haben den gleichen Effekt, sind aber einfacher zu handhaben, da du nicht selbst mit Pointern arbeiten musst. Wenn du allerdings z.B. zwei solche Werte addieren möchtest, machen Records mit überladenen Operatoren natürlich am meisten Sinn.


Tranx - Di 12.02.13 04:57

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Deine Funktion TueWasAnderes ist so nicht korrekt, denn du benutzt einen nicht initialisierten Pointer. Wenn du einen Pointer auf einen Record verwendest, musst du den auch immer erst mit New initialisieren, damit der Speicher überhaupt reserviert und der Pointer darauf zugewiesen ist.


Danke für den Hinweis. Man, manchmal ist man aber auch verbaut. Klar muss man einen Pointer auf eine Struktur erst mit New erzeugen.

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:

Die Zuweisung in einer Property funktioniert nicht als direkter Wert innerhalb des Records, da der Record beim Abrufen der Property kopiert wird. Damit arbeitest du nur auf einer temporären Kopie, würdest die Änderungen also nicht in den echten Record schreiben. Das erkennt der Compiler, da du das sicher nicht meintest.

Das ist auch der Hintergrund dessen, dass ein Pointer auf einen Record oft schneller in der Benutzung ist:
Da wird nur der Pointer kopiert, aber wenn du hingegen direkt den Record nutzt, stets der gesamte Recordinhalt.

Statt mit Pointern auf Records herumzuhantieren würde ich dir allerdings eher zu Klassen und Objekten raten. Die haben den gleichen Effekt, sind aber einfacher zu handhaben, da du nicht selbst mit Pointern arbeiten musst. Wenn du allerdings z.B. zwei solche Werte addieren möchtest, machen Records mit überladenen Operatoren natürlich am meisten Sinn.


Auch danke hierfür. Habe die lokale Zuweisung zurückgenommen und arbeit nun mit dem direkten Bezug auf die Variable in der Klasse. Das macht weniger Probleme.


WasWeißDennIch - Di 12.02.13 08:35

Evtl. interessant in dem Zusammenhang: http://www.delphipraxis.net/171740-record-schreibgeschuetzt-weil-feld-von-klasse.html [http://www.delphipraxis.net/171740-record-schreibgeschuetzt-weil-feld-von-klasse.html]