最近我有一个dillema。
考虑这样的例子:
unit Unit2;
interface
uses
Classes;
type
TMyObject = class(TObject)
private
FDataStream: TMemoryStream;
procedure SetDataStream(const Value: TMemoryStream);
public
property DataStream: TMemoryStream read FDataStream write SetDataStream;
constructor Create(ADataStream: TMemoryStream);
destructor Destroy;
end;
implementation
{ TMyObject }
constructor TMyObject.Create(ADataStream: TMemoryStream);
begin
FDataStream := ADataStream;
end;
destructor TMyObject.Destroy;
begin
//Should MyObject free FDataStream?
end;
procedure TMyObject.SetDataStream(const Value: TMemoryStream);
begin
FDataStream := Value;
end;
end.
如您所见,TMyObject可以有一个TMemoryStream实例。现在,我想知道TMyobject在被释放时应该做什么?它是否还应该释放FDataStram还是它应该保留原样?
这样的场景是否有任何指导?
感谢。
答案 0 :(得分:10)
在示例中,您认为TMyObject从其他地方接收实例。如果它不在TMyObject构造函数中来接管它收到的流的所有权,它肯定不会在它被销毁时释放它。
为了保持理智,坚持这条规则:实例化对象的类/代码应该销毁它。
由于构造函数不创建数据流实例,因此析构函数不应释放它。
答案 1 :(得分:3)
TMyObject没有创建TMemoryStream本身。该流作为对TMyObject的引用通过构造函数给出,因此TMyObject不应该释放它。释放内存流是创建它的人的责任。
答案 2 :(得分:1)
是否应该释放它取决于语义。如果您是流的唯一用户并且(之前的)所有者假设您拥有它,那么您应该在完成时释放它。
这由用户代码表示,例如:
x := TMyCode.Create(TMemoryStream.Create));
当您是所有者时,用户只需创建流(内存,文件等)并交给您。
但是,如果您只获得其他代码拥有的内存流以便读取某个部分,然后该流的所有者将其传递给另一个类/例程,那么它不是您的,您应该保持它存活。
这一切都取决于明确的文件,表明谁将释放什么。它并不像以前的海报那样清晰。您(以及您班级的用户)只能决定什么是最好的。
您当然可以添加另一个布尔属性/参数,指示您的类是否拥有该对象。但只有在不清楚班级是否应该这样做的情况下才能这样做。
答案 3 :(得分:1)
拥有该对象的对象应该释放它。通常,创建它的对象是所有者。在99%或更多的情况下就是这种情况。有时所有权转移到另一个对象,当发生这种情况时,新所有者有责任释放该对象。
虽然我会指出在你的例子中,你在Destroy中放入什么并不重要,因为它永远不会被调用 - 你忘了用override指令标记它。