1.堆与栈 heap and stack

在栈中,处理器直接使用栈指针(stack pointer)分配和访问内存。这种方式具有速度快、效率高的优点。但必须由Delphi编译器来编译产生控制栈指针的程序代码,掌握数据在栈中占用的空间大小和存活时间。这样就限制了程序的灵活性,比如Delphi对基本数据类型的规定就比较死,编译时还要进行强制性检查。所以,我们不能将对象存储在栈中,只能将对象的引用存储在栈中。从某种程度上来说,也是考虑到对象的大小和生命期是不确定的,而对象的引用的大小和生命期是可以确定的。因此,栈中的变量不需要由程序员手工去释放空间。

堆是一种通用性质的内存存储空间,是真正存放对象的地方。编译器无需知道对象从堆中分配了多少空间的内存,要占用多少时间。因此,这种方式可以获得很大的灵活性。但是,这种方式也决定了要手工分配内存,手工释放内存。效率会比栈低一些。

 2.析构问题,Free和Destroy

析构函数(Destructor)的名字一般是Destroy,但是我们在程序中销毁对象时常常用Free。Free函数来自TObject:

procedure TObject.Free;

begin

   if Self <> nil then

    Destroy;

end;

所以,对象.Free和对象.Destroy的区别在于,前者会检查对象是否存在,存在的话才调用Destroy。所以,程序中应该尽量用Free来销毁对象。

另外,在销毁一个全局对象变量时,总是把该变量设为nil,这样不会留下一个含非法指针的变量。特别,当析构函数或一个由析构函数调用的方法引用了该变量时,如果该变量成为了nil,则可以避免任何潜在的问题。

在SysUtils单元中,有个FreeAndNil的过程,可以Free,又可以将变量置为nil。如:

GlobalVar := TheNewClass.Create;
try
  GlobalVar.Over;
finally
  FreeAndNil(GlobalVar);
end;