TADOConnection.Execute
函数返回_Recordset
。
我目前正在使用此代码以简化(1):
V := ADOConnection1.Execute(SQL).Fields[0].Value;
我知道记录集从不为空所以不用担心BOF
。
现在我可以用本地_Recordset
变量(2)这样写它。
var
rs: _Recordset;
rs := ADOConnection1.Execute(SQL);
V := rs.Fields[0].Value;
多一点代码。
现在我的问题是:由于_Recordset
是Execute函数返回的接口变量,如果我不使用本地rs
变量(1)?正在使用我的简化代码(1)安全,这里是否存在引用计数问题?
我想就此问题获得一些见解。
编辑:我的问题仅针对此案:
V := ADOConnection1.Execute(SQL).Fields[0].Value
我没有_Recordset
的本地变量引用。
答案 0 :(得分:4)
试试这个:创建一个包含单行的过程
V := AdoConnection1.Execute(Sql).Fields[0].Value;
,在它上面放置一个断点来运行应用程序并查看反汇编。你会在行
之前看到它jmp @HandleFinally
有三次调用
call @IntfClear
编译器释放它必须访问的三个接口才能执行该语句,即
因此,它在执行源语句后自动生成释放这些接口所需的代码。
以下是一个不完美的类比,但它的拆卸更容易遵循;它说明了编译器自动生成的代码,用于处理最终化接口。
鉴于
type
IMyInterface = interface
function GetValue : Integer;
end;
TMyClass = class(TInterfacedObject, IMyInterface)
function GetValue : Integer;
destructor Destroy; override;
end;
TForm1 = class(TForm)
[...]
procedure Button1Click(Sender: TObject);
end;
destructor TMyClass.Destroy;
begin
inherited;
end;
function TMyClass.GetValue: Integer;
begin
Result := 1;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
I : IMyInterface;
begin
I := TMyClass.Create;
Caption := IntToStr(I.GetValue);
end;
Button1Click的CPU反汇编看起来像这样
,红色箭头表示尽管源代码清除了界面 没有做任何明确的事情来做这件事。
上设一个断点inherited
在TMyClass.Destroy中的你会发现它也会被调用,尽管如此 源代码没有明确地调用它。
就像我说的,上面是一个不完美的类比。一个有趣的事情是,对于可怕的(来自使用"使用"构造)的替代
procedure TForm1.Button1Click(Sender: TObject);
begin
with IMyInterface(TMyClass.Create) do
Caption := IntToStr(GetValue);
end;
使用no(显式)局部变量,编译器生成完全相同的代码,如图所示的反汇编。
当然,q中的情况略有不同,因为分配给记录集对象的内存位于Ado COM接口的另一端,因此无法控制该内存是否在事实之外正确解除分配编译器将生成代码以在其接口上调用_Release。