Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Pointer statt Pass-by-reference
tuedeltue - Di 10.09.13 14:39
Titel: Pointer statt Pass-by-reference
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure WorkWithFiles(s: TStrings); var i: Integer; begin for i := 0 to s.Count-1 do ShowMessage(s[i]); end;
procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog1.Execute then WorkWithFiles(OpenDialog1.Files); end; |
So war mein Code und hat auch funktioniert. Jetzt wollte ich allerdings Speicher sparen und den Parameter als Referenz übergeben:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure WorkWithFiles(var s: TStrings); var i: Integer; begin for i := 0 to s.Count-1 do ShowMessage(s[i]); end;
procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog1.Execute then WorkWithFiles(OpenDialog1.Files); end; |
Das bringt folgenden Fehler:
Quelltext
1:
| Constant object cannot be passed as var parameter |
Also hab ich folgendes geändert:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure WorkWithFiles(p: Pointer); var i: Integer; begin for i := 0 to TStringList(p^).Count-1 do ShowMessage(TStringList(p^)[i]); end;
procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog1.Execute then WorkWithFiles(Addr(OpenDialog1.Files)); end; |
So funktioniert es, aber - da ich mit Pointern nicht ganz vertraut bin wollte ich nachfragen - ist das so auch alles korrekt?
baumina - Di 10.09.13 15:01
Soviel ich weiß, ist eine class (wie z.b. TStrings) bereits ein Pointer. Deswegen kannst dir das var und die pointerei sparen.
jfheins - Di 10.09.13 15:09
Korrekt. Da werden keine Strings herumkopiert, da wird lediglich der Verweis auf die StringList weitergegeben.
Kleiner Tipp: Fange nicht an auf gut Glück RAM zu sparen, ohne dass du vorher entsprechende Probleme hattest ;-)
tuedeltue - Di 10.09.13 17:00
Aha, gut zu wissen! :wink: Aber prinzipiell war alles richtig, oder?
WasWeißDennIch - Di 10.09.13 18:38
Das würde ich nicht unterschreiben. Um Pointer (also auch Objektinstanzen) als Var- oder Out-Parameter zu übergeben, sollte man einen triftigen Grund haben, sonst kann man sich schnell selbst ins Knie schießen.
mandras - Di 10.09.13 18:49
tuedeltue hat folgendes geschrieben : |
Aha, gut zu wissen! :wink: Aber prinzipiell war alles richtig, oder? |
Jein.
Mit der Pointerlösung umgehst Du die Prüfungen des Compilers der ja zu Recht bei der Übergabe als VAR meckert.
Grund:
Files im Dialog ist zwar eine Stringlist, aber nur lesbar (da als Poperty ohne Setter realisiert).
Was als VAR übergeben wird muß prinzipiell auch beschreibbar sein.
WasWeißDennIch - Di 10.09.13 18:52
AFAIK können Properties generell nicht als Var-Parameter übergeben werden, auch wenn ein Setter vorhanden ist.
mandras - Di 10.09.13 18:54
WasWeißDennIch hat folgendes geschrieben : |
AFAIK können Properties generell nicht als Var-Parameter übergeben werden, auch wenn ein Setter vorhanden ist. |
Das ohnehin (ein VAR muß ein Speicherbereich sein, Properties können ja auch Procedures/Functions darstellen), meine Erklärung zielte auf die Compilermeldung bzgl. "constant" ab.
WasWeißDennIch - Di 10.09.13 18:55
Ah OK, dann sind wir uns ja einig :wink:
tuedeltue - Mi 11.09.13 19:26
mandras hat folgendes geschrieben : |
Jein. Mit der Pointerlösung umgehst Du die Prüfungen des Compilers der ja zu Recht bei der Übergabe als VAR meckert. |
Das war schon so verstanden. Die Frage war, ob - von den möglichen Probleme beim Zugriff auf Properties via Pointer abgesehen - der Code zum Einsatz des Pointers korrekt ist. Aber ich interpretiere dein Jein mal entsprechend und denke also schon. :wink:
Zur ursprünglichen Frage: ich habe jetzt wieder Variante 1 von ganz oben im Code stehen. Das ist so also richtig und es gibt keine Verbesserungen, ja?
IhopeonlyReader - Mi 11.09.13 21:58
nein, speicher kannst du 4 Byte sparen (den Pointer bzw. TStrings) indem du Work with Files direkt in Button1Click einbaust.
Aber wenn du für 4 Byte deinen kompletten Quelltext unübersichlich machen willst. Das ist nicht mein Code, den ich evt ín 1 jahr noch verstehen will :D#
P.S: ich bin mir nichtmal sicher ob du da 4 Byte sparst :D
glotzer - Mi 11.09.13 22:56
IhopeonlyReader hat folgendes geschrieben : |
mir nichtmal sicher ob du da 4 Byte sparst :D |
Soweit ich weiß nicht, da der erste Parameter Normalerweiße in einem Register steht. (glaub es war EAX)
WasWeißDennIch - Do 12.09.13 08:12
Wie soll man da etwas sparen? Ein Pointer hat unter 32 Bit 4 Byte, eine Instanz ist intern ein Pointer, es sind also immer 4 Byte, egal ob ich die Referenz übergebe oder einen Pointer darauf. Das Problem bei einem Pointer als Var-Paramter ist doch, dass sich dieser innerhalb der verarbeitenden Routine ändern lässt und sich das auf das Original auswirkt. Somit kann es passieren, dass nach der Verarbeitung plötzlich ein ganz anderes Objekt angesprochen wird.
Xion - Sa 14.09.13 12:44
Also wenn, dann definiere deine Prozedur als inline.
Delphi-Quelltext
1:
| procedure WorkWithFiles(s: TStrings); inline; |
Dann wird der Inhalt der Funktion an der aufrufenden Stelle eingesetzt (als würde dort der Code selbst stehen, die Procedure wird sozusagen aufgelöst). Dann sparst du dir einen Funktionsaufruf, was dir etwas Rechenzeit sparen kann.
An sich geht es bei der Diskussion sowieso kaum um "Speicher" sparen, denn der Parameter wird ja ohnehin nur benötigt, solange die Prozedur läuft...und der Parameter kommt auf den Stack. Der Stack ist aber sowieso reserviert. Die "freien" Bytes kannst du also garnicht nutzen. Es geht bei call by reference (in Bezug auf Performanz) eher darum, dass nicht so viel Speicher geschrieben werden muss (also CPU-Zyklen) als um Speicherbedarf an sich.
Speicherverwaltung in Delphi (englisch):
http://delphi.about.com/od/windowsshellapi/a/heap-stack-explained-for-delphi-developers.htm
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!