Oop 对象Pascal:必须释放所有对象(类)吗?
我可以在不释放它们的情况下到处乱扔Oop 对象Pascal:必须释放所有对象(类)吗?,oop,pascal,freepascal,delphi,Oop,Pascal,Freepascal,Delphi,我可以在不释放它们的情况下到处乱扔类es吗,或者我的软件会开始泄漏吗 例如,我可以这样做吗 Engine := TEngine.Create(TV); 然后毫无问题地摆脱引用,或者我必须首先调用它的Free方法吗 或者使用一个函数返回一个t某物,并且以后不必释放它的引用?一般规则是,如果创建它,就应该释放它。最好的方法是尝试。最后,如果您使用代码创建它: var Engine: TEngine; begin Engine := TEngine.Create(TV); try
类
es吗,或者我的软件会开始泄漏吗
例如,我可以这样做吗
Engine := TEngine.Create(TV);
然后毫无问题地摆脱引用,或者我必须首先调用它的Free
方法吗
或者使用一个函数返回一个
t某物
,并且以后不必释放它的引用?一般规则是,如果创建它,就应该释放它。最好的方法是尝试。最后,如果您使用代码创建它:
var
Engine: TEngine;
begin
Engine := TEngine.Create(TV);
try
// Do stuff with Engine
finally
Engine.Free;
end;
end;
例外情况是,如果您有一个接受所有者作为参数的对象(例如像TEdit
这样的可视控件或TComponent
的非可视后代)。如果分配所有者,则在释放所有者时将释放它。(如果您在没有所有者的情况下创建它,您仍然需要自己释放它。)
如果该类是另一个对象的成员(字段),则在包含对象的构造函数中创建它,并在其析构函数中释放它:
type
TOuterClass = class(TObject)
private
FEngine: TEngine;
public
constructor Create;
destructor Destroy; override;
end;
implementation
constructor TOuterClass.Create;
begin
inherited;
FEngine := TEngine.Create(TV);
end;
destructor TOuterClass.Destroy;
begin
FEngine.Free;
inherited;
end;
一般的规则是,如果你创建了它,你应该释放它。最好的方法是尝试。最后,如果您使用代码创建它:
var
Engine: TEngine;
begin
Engine := TEngine.Create(TV);
try
// Do stuff with Engine
finally
Engine.Free;
end;
end;
例外情况是,如果您有一个接受所有者作为参数的对象(例如像TEdit
这样的可视控件或TComponent
的非可视后代)。如果分配所有者,则在释放所有者时将释放它。(如果您在没有所有者的情况下创建它,您仍然需要自己释放它。)
如果该类是另一个对象的成员(字段),则在包含对象的构造函数中创建它,并在其析构函数中释放它:
type
TOuterClass = class(TObject)
private
FEngine: TEngine;
public
constructor Create;
destructor Destroy; override;
end;
implementation
constructor TOuterClass.Create;
begin
inherited;
FEngine := TEngine.Create(TV);
end;
destructor TOuterClass.Destroy;
begin
FEngine.Free;
inherited;
end;
从技术上讲,是的,必须显式释放使用构造函数初始化的所有内容 但有一些简单的解决方法,如果使用得当,可以为您省去大部分麻烦: 1:使用TInterfacedObject:
IMyStuff = interface(IUnknown)
['{9DF82155-2475-4403-8933-969DC4912AD7}']
function Print:boolean;
procedure DoStuff;
end;
TMyStuff = class(TInterfacedObject, IMyStuff)
private
function Print:boolean;
procedure DoStuff;
end;
像其他类一样实现TMyStuff。但在代码中使用该类时,请使用IMyStuff类型的变量,如下所示:
procedure MyIProcedure;
var myStuff: IMyStuff;
begin
myStuff:=TMyStuff.create;
myStuff.DoStuff;
end;
无需在“TMyStuff.create”调用中强制转换(在本例中,有时是…),因为变量类型为IMystuff,这是隐式的。无需释放IMyStuff(事实上您不能,尽管您可以调用IMyStuff:=nil。)因为它被声明为一种接口类型,所以自动垃圾收集是使用COM引用计数模型实现的-当您从TInterfacedObject继承时,Delphi会为您处理此问题
但是不要混合类类型变量:即TMyStuff和IMyStuff变量类型。这会导致一些令人讨厌的混乱和错误,让你抓狂。这就是我通常将TInterfacedObject的成员声明为PRIVATE的原因,就像我在这里所做的那样,通过引用TMyStuff使它们在中不可访问。但是,可以通过对IMyStuff的引用来访问它们:根据定义,所有接口成员都是公共的
2:除了Ken的出色回答之外,VCL的TObjectList和TObjectDictionary还为它们包含的所有对象引用提供了自动垃圾收集(详细信息请参见Delphi文档)——但它们本身必须被释放,然后其余的都被释放
只要在TInterfacedObject的析构函数中释放ObjectList或ObjectDictionary,就可以在TInterfacedObject中使用TObjectList或TObjectDictionary,不再担心垃圾收集。当referenceCount=0时,Delph的实现将自动调用该析构函数。技术上是的,必须显式释放使用构造函数初始化的所有内容 但有一些简单的解决方法,如果使用得当,可以为您省去大部分麻烦: 1:使用TInterfacedObject:
IMyStuff = interface(IUnknown)
['{9DF82155-2475-4403-8933-969DC4912AD7}']
function Print:boolean;
procedure DoStuff;
end;
TMyStuff = class(TInterfacedObject, IMyStuff)
private
function Print:boolean;
procedure DoStuff;
end;
像其他类一样实现TMyStuff。但在代码中使用该类时,请使用IMyStuff类型的变量,如下所示:
procedure MyIProcedure;
var myStuff: IMyStuff;
begin
myStuff:=TMyStuff.create;
myStuff.DoStuff;
end;
无需在“TMyStuff.create”调用中强制转换(在本例中,有时是…),因为变量类型为IMystuff,这是隐式的。无需释放IMyStuff(事实上您不能,尽管您可以调用IMyStuff:=nil。)因为它被声明为一种接口类型,所以自动垃圾收集是使用COM引用计数模型实现的-当您从TInterfacedObject继承时,Delphi会为您处理此问题
但是不要混合类类型变量:即TMyStuff和IMyStuff变量类型。这会导致一些令人讨厌的混乱和错误,让你抓狂。这就是我通常将TInterfacedObject的成员声明为PRIVATE的原因,就像我在这里所做的那样,通过引用TMyStuff使它们在中不可访问。但是,可以通过对IMyStuff的引用来访问它们:根据定义,所有接口成员都是公共的
2:除了Ken的出色回答之外,VCL的TObjectList和TObjectDictionary还为它们包含的所有对象引用提供了自动垃圾收集(详细信息请参见Delphi文档)——但它们本身必须被释放,然后其余的都被释放
只要在TInterfacedObject的析构函数中释放ObjectList或ObjectDictionary,就可以在TInterfacedObject中使用TObjectList或TObjectDictionary,不再担心垃圾收集。当referenceCount=0时,Delph的实现将自动调用该析构函数。如果TComponent所有者机制纯粹是一种库约定,那就再强调也不过分了。在语言级别上,它仍然必须被释放,只是FCL/VCL为您做了一些管理。@KenWhite您是否还必须释放引发的
Exception
s?@SuperDisk:No.:-)您没有创建相同的代码;你在抚养他们。“异常处理机制将为您解决这些问题。@KenWhite好的,最后一个问题。是否必须立即释放传递给过程的新类?例如,如果调用DoThing(TCoord.Create(0,0))你知道吗