Delphi演员:内存泄漏?
Delphi Cast: Memory leak?
在 Delphi 中,我从已经创建的基础 class 中转换继承的 class。我相信这会在两个 classes 之间共享基础 class 地址,但是继承的 class 的额外成员会获得分配给它们的额外内存,但不会被初始化。
如果随后释放共享基 class,这是否会导致 Inherited 的 class 成员发生内存泄漏?
如果是这样,如果我想保持基础 class 不变,清理继承的 classes 成员的最佳方法是什么?
program Project1;
uses
SysUtils;
type
TBase = class(TObject)
public
basemember : string ;
Constructor Create() ;
end;
TInherited = class(TBase)
public
inheritedmember : string ;
Constructor Create() ;
end ;
Constructor TBase.Create() ;
begin
basemember := 'Basemember' ;
Writeln ('basemember') ;
end ;
Constructor TInherited.Create() ;
begin
inheritedmember := 'inheritedmember' ;
Writeln ('inheritedmember') ;
end ;
var
baseclass : TBase;
castbaseclass : TInherited;
begin
Writeln ('Base Class');
baseclass := TBase.Create();
Writeln ('');
Writeln ('Cast Inherited Class');
castbaseclass := TInherited(baseclass);
baseclass.Free; //memory leak?
ReadLn;
end.
这里没有内存泄漏,但是强制转换还是错误的。
您关注的是这行代码:
castbaseclass := TInherited(baseclass);
由于Delphiclass都是引用类型,所以baseclass
和castbaseclass
都是指针。您在这里所做的一切都被分配了一个指针变量。您随后再也没有提到 castbaseclass
。如果你这样做了,那么可能会出现运行时错误,因为编译器认为 castbaseclass
是一个 TInherited
实例,但实际上它是一个不太专业的 class 的实例, TBase
.
但是,你的误会很深
I'm casting an inherited class from a base class which is already created. I believe this shares the base class addresses between the two classes, but the inherited's class's extra members get extra memory allocated to them, but are not initialised.
没有!绝对不。为了实例化 TInherited
实例,您必须调用 TInherited
的构造函数。您不能创建一个 class 的实例并期望它永远变形为另一个 class。实例的类型在实例创建时就一劳永逸地确定下来了。实例的内存是在创建实例时分配的,其他时间不会分配。
因此,如果您想要 TInherited
,请创建一个。如果您想要 TBase
,请创建一个。但是您不能创建 TBase
并将其类型更改为 TInherited
。您可以做的是创建一个 TInherited
,然后将其分配给类型为 TBase
的变量。那是因为 TInherited
派生自 TBase
.
所以你可以这样写:
var
base: TBase;
inherited_: TInherited; // _ because inherited is a keyword
....
inherited_ := TInherited.Create;
base := inherited_;
但是你不能写:
var
base: TBase;
inherited_: TInherited;
....
base := TBase.Create;
inherited_ := base;
在 Delphi 中,我从已经创建的基础 class 中转换继承的 class。我相信这会在两个 classes 之间共享基础 class 地址,但是继承的 class 的额外成员会获得分配给它们的额外内存,但不会被初始化。
如果随后释放共享基 class,这是否会导致 Inherited 的 class 成员发生内存泄漏?
如果是这样,如果我想保持基础 class 不变,清理继承的 classes 成员的最佳方法是什么?
program Project1;
uses
SysUtils;
type
TBase = class(TObject)
public
basemember : string ;
Constructor Create() ;
end;
TInherited = class(TBase)
public
inheritedmember : string ;
Constructor Create() ;
end ;
Constructor TBase.Create() ;
begin
basemember := 'Basemember' ;
Writeln ('basemember') ;
end ;
Constructor TInherited.Create() ;
begin
inheritedmember := 'inheritedmember' ;
Writeln ('inheritedmember') ;
end ;
var
baseclass : TBase;
castbaseclass : TInherited;
begin
Writeln ('Base Class');
baseclass := TBase.Create();
Writeln ('');
Writeln ('Cast Inherited Class');
castbaseclass := TInherited(baseclass);
baseclass.Free; //memory leak?
ReadLn;
end.
这里没有内存泄漏,但是强制转换还是错误的。
您关注的是这行代码:
castbaseclass := TInherited(baseclass);
由于Delphiclass都是引用类型,所以baseclass
和castbaseclass
都是指针。您在这里所做的一切都被分配了一个指针变量。您随后再也没有提到 castbaseclass
。如果你这样做了,那么可能会出现运行时错误,因为编译器认为 castbaseclass
是一个 TInherited
实例,但实际上它是一个不太专业的 class 的实例, TBase
.
但是,你的误会很深
I'm casting an inherited class from a base class which is already created. I believe this shares the base class addresses between the two classes, but the inherited's class's extra members get extra memory allocated to them, but are not initialised.
没有!绝对不。为了实例化 TInherited
实例,您必须调用 TInherited
的构造函数。您不能创建一个 class 的实例并期望它永远变形为另一个 class。实例的类型在实例创建时就一劳永逸地确定下来了。实例的内存是在创建实例时分配的,其他时间不会分配。
因此,如果您想要 TInherited
,请创建一个。如果您想要 TBase
,请创建一个。但是您不能创建 TBase
并将其类型更改为 TInherited
。您可以做的是创建一个 TInherited
,然后将其分配给类型为 TBase
的变量。那是因为 TInherited
派生自 TBase
.
所以你可以这样写:
var
base: TBase;
inherited_: TInherited; // _ because inherited is a keyword
....
inherited_ := TInherited.Create;
base := inherited_;
但是你不能写:
var
base: TBase;
inherited_: TInherited;
....
base := TBase.Create;
inherited_ := base;