Iva*_*nov 2 delphi optimization static dynamic delphi-2009
我不止一次被告知Delphi比static更好地处理动态类.使用以下代码:
type Tsomeclass=class(TObject)
private procedure proc1;
public
someint:integer;
procedure proc2;
end;
var someclass:TSomeclass;
implementation
...
initialization
someclass:=TSomeclass.Create;
finalization
someclass.Free;
Run Code Online (Sandbox Code Playgroud)
而不是
type Tsomeclass=class
private class procedure proc1;
public
class var someint:integer;
class procedure proc2;
end;
Run Code Online (Sandbox Code Playgroud)
我正在处理的项目中有90%的类只需要一个实例.我真的必须使用第一种方法来使用这些类吗?是否更好地优化,由Delphi处理?
对不起,我没有理由支持这个假设,但我想要专家的意见.
提前致谢!
gab*_*abr 11
如果您创建的类只包含类变量和类方法,那么您可以在不实例化的情况下使用它.即在你的第二个例子中,你可以使用Tsomeclass.proc2(但不是Tsomeclass.someint,因为这个变量没有用Uwe指出的'class'前缀标记).
对于(不可避免的小)速度差异,您还可以将类方法标记为"静态".
type
TSomeclass = class
class procedure proc2; static;
end;
Run Code Online (Sandbox Code Playgroud)
在我看来,这里没有"处理更好"的比较.Delphi允许您在课堂上放置"普通"和"课堂"成员.以前只能在实例化对象上使用,后者可以在任何地方使用.但这只是Delphi中OO支持的两个部分.
编辑:回答关于速度的问题......
让我们整理一个小测试程序:
program Project61;
{$APPTYPE CONSOLE}
type
TTestClass = class
procedure A(a: integer);
class procedure B(b: integer);
class procedure C(c: integer); static;
end;
procedure TTestClass.A(a: integer); begin end;
class procedure TTestClass.B(b: integer); begin end;
class procedure TTestClass.C(c: integer); begin end;
var
tc: TTestClass;
begin
tc := TTestClass.Create;
tc.A(42);
tc.B(42);
tc.C(42);
tc.Free;
//TTestClass.A(42); // not possible
TTestClass.B(42);
TTestClass.C(42);
end.
Run Code Online (Sandbox Code Playgroud)
Delphi 2010启用了优化编译.A/.B/.C调用
Project61.dpr.30: tc := TTestClass.Create;
004060C5 B201 mov dl,$01
004060C7 A154594000 mov eax,[$00405954]
004060CC E847DAFFFF call TObject.Create
004060D1 8BD8 mov ebx,eax
Project61.dpr.31: tc.A(42);
004060D3 BA2A000000 mov edx,$0000002a
004060D8 8BC3 mov eax,ebx
004060DA E899F9FFFF call TTestClass.A
Project61.dpr.32: tc.B(42);
004060DF BA2A000000 mov edx,$0000002a
004060E4 8B03 mov eax,[ebx]
004060E6 E891F9FFFF call TTestClass.B
Project61.dpr.33: tc.C(42);
004060EB B82A000000 mov eax,$0000002a
004060F0 E88BF9FFFF call TTestClass.C
Project61.dpr.34: tc.Free;
004060F5 8BC3 mov eax,ebx
004060F7 E84CDAFFFF call TObject.Free
Project61.dpr.36: TTestClass.B(42);
004060FC BA2A000000 mov edx,$0000002a
00406101 A154594000 mov eax,[$00405954]
00406106 E871F9FFFF call TTestClass.B
Project61.dpr.37: TTestClass.C(42);
0040610B B82A000000 mov eax,$0000002a
00406110 E86BF9FFFF call TTestClass.C
Run Code Online (Sandbox Code Playgroud)
首先创建对象,并将其地址存储到ebx寄存器中.
要调用tc.A,编译器会在edx中准备参数(42或$ 2A),即eax中'tc'实例的地址并调用TTestClass.A.
除了ebx被解除引用之外,在tc.B情况下几乎相同.
在.A和.B情况下,eax包含'Self'的值(相当于C++的'this').当调用tc.A时,eax包含'tc'实例的地址.当调用tc.B时,eax包含其他内容(我猜它指的是TTestClass的类型信息,但我并不确定).
当代码调用tc.C时,只准备了eax,因为'static'方法不能引用'Self'.
类似的情况发生在TTestClass.B/.C的情况下,除了'Self'是从TTestClass typeinfo的??地址从某个常量位置加载的?被储存了.无论如何,当通过实例(tc.B)或通过类(TTestClass.B)调用B时,eax包含相同的值.
所以你可以看到静态调用需要一个'mov'.那是我提到的无法估量的加速.