我在论坛上阅读了许多关于指针,Assigned
函数,Free
函数,FreeAndNil
函数等的帖子...我已经知道自由函数不会删除指针引用分配的对象和FreeAndNil
这样做...我读过的所有帖子都考虑到Create
方法已经执行了,或者换句话说,考虑已经创建的对象。
我的问题是:为什么Assigned
函数对未初始化的对象变量返回true?
举个例子:
procedure TForm1.FormCreate(Sender: TObject);
var
Qry: TADOQuery;
begin
if Assigned(Qry) then
ShowMessage('Assigned')
else
ShowMessage('Unassigned');
Qry := TADOQuery.Create(nil);
if Assigned(Qry) then
ShowMessage('Assigned')
else
ShowMessage('Unassigned');
end;
该示例显示“已分配”两次!
结论:在声明Qry
之后,在执行其创建方法之前,Qry
的指针不是NIL
!
如果我将Qry := nil;
放在上面第一行的程序中,一切正常......它显示'未分配'和'已分配'。
为什么?
有没有什么安全的方法可以知道类变量是否已经执行了create方法?
答案 0 :(得分:7)
您的变量是局部变量,因此未初始化。它可以包含任何值。
在Win32平台上,内容为 在分配值之前,未定义局部变量 它们。
请注意,作为实现细节,管理某些类型,甚至初始化托管类型的局部变量。托管类型的示例包括:字符串,接口,动态数组,匿名类型和变体。
你问:
有没有什么安全的方法可以知道类变量是否已经执行了create方法?
如果该变量是局部变量,则答案为否。程序员有责任落在你身上。在实践中,它很少成为问题,因为良好的代码具有较短的程序,这使得您更难以滑倒。即使你这样做,编译器也会一直警告你。
初始化其他类型的变量,如类字段和全局变量。
答案 1 :(得分:5)
从Assigned
函数的文档(强调我的):
使用Assigned确定P引用的指针或过程是否为nil。 P必须是指针或过程类型的变量引用。 分配(P)对应于测试P<>。 nil表示指针变量,@ P<> nil为程序变量。
如果P为nil,则赋值返回false,否则返回true。
注意:Assigned无法检测到悬空指针 - 也就是说,指针不是nil但不再指向有效数据。例如,在Assigned的代码示例中,Assigned将不会检测P无效的事实。
Assigned
函数有效实现为:
function Assigned(const P): Boolean;
begin
Result := Pointer(P) <> nil;
end;
因此该函数并未真正检查该值是否真正分配。相反,它正在检查被分配的副作用。
True
。另一点需要注意的是Assigned
无法确定其值的有效性。例如。即使基础对象不再有效,以下对Assigned
的调用也会返回True
。
var
LObject: TObject;
begin
LObject := TObject.Create;
LObject.Free;
if Assigned(LObject) then ShowMessage('Still assigned!?');
end;
编辑:附录
回答你问题的第二部分。
有没有什么安全的方法可以知道类变量是否已经执行了create方法?
没有安全的方法来确定是否已创建对象实例。 (也没有办法可靠地确认它还没有被销毁。)
但是,您可以遵循一些惯例(和良好做法)来帮助您。
首先请注意,如果某些内容被创建,那么您应该只是“不确定”,如果它是该段代码的故意特征。例如。如果你想让一个对象“懒惰初始化”。
Assigned
只是因为您担心可能存在阻止其被分配的错误。所以现在我们(希望)同意你只检查是否创建,如果你故意选择创建是可选的。您可以按如下方式执行此操作:
答案 2 :(得分:3)
因为在创建指针时,它带有该内存位置中的任何垃圾值。如果你想在其中编写NIL,它需要一些CPU周期,我认为它不是由Delphi自动完成的,因为你可能想要更快的东西。在您的示例中,为什么要将NIL分配给变量,如果不久之后您又要在其中添加另一个值?