vložil Radek Červinka
18. listopadu 2011 23:03
Jen pro zajímavost pro začátečníky malé zamyšlení o řetezcích, Exception.CreateFmt a podobných funkcích.
Mějme následující kód:
1program Project1;
2
3
4
5uses
6 SysUtils;
7
8 procedure m1(i:Integer);
9 begin
10 if i <> 1 then
11 raise Exception.Create(Format('Error Message:%d', [i]));
12 end;
13 procedure m2(i:Integer);
14 begin
15 if i <> 1 then
16 raise Exception.CreateFmt('Error Message:%d', [i]);
17 end;
18 procedure m3(i:Integer);
19 begin
20 if i <> 1 then
21 raise Exception.Create('Error Message:'+ IntToStr(i));
22 end;
23
24begin
25 try
26 m1(1);
27 m2(1);
28 m3(1);
29 readln;
30 except
31 on E: Exception do
32 Writeln(E.ClassName, ': ', E.Message);
33 end;
34end.
V případě uvedených volání sice nedojde k výjimce, ale otázkou je co je i tak nejefektivnější a proč?
Kompilátor musí zaručit uvolňování dynamických struktur jako jsou řetězce a různá pole na konci bloku kódu (tj. procedury). Podívejme se na ukázkové příklady:
V prvním případě je pro parametr výjimky volána funkce Format a výsledný řetězec je předán do konstruktoru.
V druhém případě jsou parametry předány do jiného konstruktoru a v rámci této funkce není prováděno žádné jiné volání.
Třetí případ potencionálně volá IntToStr a spojuje řetězce.
Nejméně efektivní je poslední volání, protože kompilátor vygeneruje interní sekci finally, která provede uvolnění potencionálních řetězců (parametry Exception.Create). Pokud se podíváme do přeloženého kódu uvidíme volání @UStrArrayClr. V případě, že nedojde k výjimce je toto volání provedeno nejkratší možnou cestou jelikož žádné řetězce nejsou, ale přesto je provedeno.
Pokud se podíváme na první příklad (m1), tak uvidíme podobnou situaci, jen je voláno @UStrClr, které uvolní jediný potencionální dočasný řetězec, který je výsledkem volání Format. Pokud nedošlo k výjimce, je z funkce @UStrClr vyskočeno hned na začátku.
No a nakonec tu máme příklad m2 - zde se žádný dočasný řetězec nevyskytuje, takže se žádný ani neuvolňuje, parametry se předávají přímo do volané funkce. Výsledkem je, že není generována žádná sekce "finally" a ani žádné uvolňování.
Co z toho plyne? Delphi (a asi i další vyšší jazyky) kouzlí a je třeba aspoň trochu chápat jak to asi funguje. Výsledkem může pak být jedině lepší kód.