![]() |
Re: Function/Procedure -Deklaration ?!
Wenn du das var voranstellst, dann wird einfach die Speicheradresse überschreiben, das braucht natürlich nicht mehr Speicher, aber ohne das var wird ja eine Kopie der Variable angelegt, somit sollte das dann etwas mehr Speicherplatz verbrauchen.
Das mit den 4 Bytes stimmt, wenn man const und var betrachtet, aber ohne diese beiden müsste es theoretisch doch mehr verbrauchen. :gruebel: Oder nicht? |
Re: Function/Procedure -Deklaration ?!
Moin!
Zitat:
MfG Muetze1 |
Re: Function/Procedure -Deklaration ?!
Zitat:
Übrigens kann man const-paras deshalb sehr wohl beschreiben, wenn man bischen mit ^ und @ rumspielt:
Delphi-Quellcode:
Allerdings nur bei werten > 4 byte...oder so!
type
pPoint = ^TPoint; procedure Foo(const bar:TPoint); begin pPoint(@bar)^ := Point(10,20); end; procedure TForm1.Button1Click(Sender: TObject); var c:TPoint; begin c := Point(0,0); foo(c); ShowMessage(intToStr(c.X)+','+intToStr(c.Y)); end; |
Re: Function/Procedure -Deklaration ?!
Hallo Leute
Habe eure Diskussion verfolgt. Folgendes macht Delphi bei den Übergabeattributen: Fall 1:
Code:
Fall 2:
procedure Test(a: string) -> call by value
Code:
Fall 3:
procedure Test(const a: string) -> call by reference
Code:
Beim Fall 1 wird der String als "call by Value" übergeben. Da es sich hierbei um einen string = (Objekt) handelt, sind einige Maschinencodeanweisungen notwendig. Wenn man im FPU-Debugger die erzeugten Anweisungen ansieht, kommen dabei um die 30 Assembleranweisungen zusammen.
procedure Test(var a: string) -> call by reference
Beim Fall 2 und 3 wird der String als "call by reference" übergeben. Dabei handelt es sich nur mehr um die Speicheradresse der Variablen (4 Byte), die über den Stack übergeben wird. Dafür ist nur mehr eine Maschinencodeanweisung notwendig. Geschwindigkeitsmäßig sollten Fall 2 und Fall 3 gleich schnell sein. (Informationen stammen von meinem Persönlichen Delphi Lehrer) Mfg Mike. PS. Habe mich also geirrt, Const ist schneller als ohne was, aber nicht schneller als var... :wall: |
Re: Function/Procedure -Deklaration ?!
Moin!
Ok, ich habe das ganze jetzt nochmal debuggt und folgendes kam dabei raus: alle 3 Formen haben ein und die selbe Übergabeform: EAX = Self der Form EDX = Zeiger auf den String Die Funktionen sind alle gleich vom Aufruf her - was durch den Variablentyp mit einer Grösse > 4 auch kein Wunder ist - vor allem wird bei Strings so oder so nur mit einer Instanzenaddresse gearbeitet.
Code:
Der Unterschied besteht bei der 1. Funktion wo kein Const und kein Var angeben wurde, dort wird vor dem Aufruf von Trim() sicher gestellt, dass es keine anderen Referenzen auf den String gibt - also wird, wenn eine Referenz da ist, diese abgespalten in einen eigenen String. Danach wird der eindeutige String nach dem Trim gelöscht - also Referenz entfernen und String löschen. Mit anderen Worten: Bei der ersten Form wird vorher keine Kopie von dem String gemacht, das macht die Funktion selber, wenn nötig - also wenn es mehr als eine Referenz auf den String gibt.
push ebp
mov ebp, esp add esp, -$08 // Platz für 2x 4 Byte machen - sichern der Var's mov [ebp-$08], edx // String sichern auf'm Stack mov [ebp-$04], eax // Instanzenzeiger sichern auf'm Stack // hier ist ein Unterschied - siehe unten mov edx, [ebp-$08] // String holen mov eax, [ebp-$04] // Instanzenzeiger holen call Trim ... Mein Testcode dazu (Optimierung aus, sonst kann man das nicht so schön sehen)
Code:
Zusammenfassung:
Function Test1(AStr : String): String;
Begin Result := Trim(AStr); End; Function Test2(Const AStr : String): String; Begin Result := Trim(AStr); End; Function Test3(Var AStr : String): String; Begin Result := Trim(AStr); End; procedure TForm1.FormCreate(Sender: TObject); Var s : String; begin s := Edit1.Text; Label1.Caption := Test1(s); Label2.Caption := Test2(s); Label3.Caption := Test3(s); end; Die Aufrufart ohne Const oder Var sorgt für grösseren Code für die Duplizierung / Dereferenzierung. Die anderen beiden Arten sind völlig gleich. Und wohl gemerkt ist trotz des Unterschiedes kein Unterschied zwischen der by value oder by reference Übergabe zu sehen, weil die Übergabe der Parameter geschieht komplett gleich - die by reference Geschichte wird von der Funktion selber sicher gestellt. MfG Muetze1 |
Re: Function/Procedure -Deklaration ?!
Danke, dass du dir die Mühe gemacht hast, find ich echt klasse! :thumb:
Nur verstehe ich's immer noch nicht genau. :-? Ist zwar Off-Topic, aber auch net so ganz. ;) |
Re: Function/Procedure -Deklaration ?!
Zitat:
|
Re: Function/Procedure -Deklaration ?!
Moin!
Mir ist ja wirklich schlecht geworden, als ich das mal mit einem ShortString gemacht habe... Die Ergebnisse: 1. Ohne Var oder Const packt er den kompletten ShortString auf den Stack! (also wenn das keine Verschwendung ist, aber wir haben's ja unter Windows) 2. Mit einem Const das gleiche, nur da ist es fast noch schlimmer: die Funktion kopiert sich von dem ShortString, der auch hier komplett auf dem Stack liegt, eine Kopie in die Stackframe. Mit anderen Worten der Stack in der Funktion sieht dann so aus, dass er einmal den kompletten ShortString als Param liegen hat auf'm Stack beim Eintritt. Dann besorgt er sich nochmal 256 Bytes Platz auf dem Stack (ESP verschieben) und kopiert in den neuen Platz den String von weiter vorne. Dann nutzt er bei den weiteren Funktionen die Kopie. 3. Die Var - Variante bekommt eine Referenz / Zeiger auf den String übergeben. Fazit: Nur die Var Methode dürfte in so fern schneller sein und vor allem Stack-freundlicher. Abhilfe: keinen ShortString verwenden, sondern einen AnsiString/String, der kann Referenzen.... MfG Muetze1 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:34 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz