Einzelnen Beitrag anzeigen

Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.041 Beiträge
 
Delphi XE2 Professional
 
#33

AW: Procedure vs Function, Vor- und Nachteile

  Alt 16. Apr 2018, 11:41
In seltenen Fällen (bei Übergabe großer Strukturen bzw. Strings, etc.) kann ein var Parameter sinnvoll sein, um Kopieroperationen zu vermeiden. Muss man sich im Normalfall aber keine Gedanken drüber machen.
Gerade da ist es total wurscht,
denn bei gemanagten Typen ala String, Variant, Interface und dynamischen Arrays macht der Delphi-Compiler aus function Beispiel(...): string; eben auch einprocedure Beispiel(...; var Result: string); und kopiert nichts um.

Leider ist das auch das Problem/die Urache, dass bei Funktionen für das Result keine "wurde nicht initialisiert"-Meldung vom Compiler kommt, da es eben doch initialisiert wurde (außerhalb)
und mit dem Ergebnis, dass bei vergessenen Initialisierung schnell etwas Komisches heraus kommt,
Delphi-Quellcode:
function Test: string;
begin
  Result := Result + 'a';
end;

for i := 1 to 5 do
  S := Test;
ShowMessage(S); // 'aaaaa'
aber wenn man sich das jetzt gedanklich als Prozedur ansieht, dann ist sofort klar, warum es so ist.
Damit würde ich aber schlaflose Nächte haben.

Result ist definitiv nicht initialisiert und besitzt einen Zufallswert, der ggf. dann von dem vorherigen Funktionsaufruf noch zufällig vorhanden ist.

Mag sein, dass das jetzt so funktioniert. Dieses Verhalten ist aber nirgends dokumentiert. (Oder ich habe es noch nicht gesehen.)

Bei einer nächsten Compilerfunktion wird das ggf. ganz anders sein.
Doch, Result ist definitiv initialisiert und besitzt keinen Zufallswert.
Bei "Function Test:String;" ist Result ein Zeiger auf eine Stringvariable und da Strings immer initialisiert werden, ist damit auch Result initialisiert.
Im nachstehenden Assembler-Auszug kannst du das schön sehen.
Vor dem Aufruf der Funktion Test wird mit lea eax,[ebp-$04] die Adresse der lokalen Variablen S in EAX gestellt.
Das in [ebp-4] tatsächlich die Variable S gespeichert ist, siehst du 6 Zeilen tiefer, wo S als Parameter für ShowMessage in EAX gestellt wird.
Recht hättest du bei z.B. Function Test:Integer;, da ist Result nicht initialisiert.

C_Main.pas.5152: for I:=1 to 5 do
0060FFF4 BB05000000 mov ebx,$00000005
C_Main.pas.5153: S:=Test;
0060FFF9 8D45FC lea eax,[ebp-$04]
0060FFFC E8B7FFFFFF call Test
C_Main.pas.5152: for I:=1 to 5 do
00610001 4B dec ebx
00610002 75F5 jnz $0060fff9
C_Main.pas.5154: ShowMessage(S);
00610004 8B45FC mov eax,[ebp-$04]
00610007 E8C0A2ECFF call ShowMessage
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat