在Delphi中,将一个对象转换为其父对象会占用更多的内存吗?

3
我正在使用一个 TMemoryStream 并且需要将它传递给一个需要TStream类型变量的过程(来自外部库)。我只需要这样强制类型转换:TMemoryStreamTStream
var
    myStream: TMemoryStream;

begin
    //...
    ExternalProcedure(TStream(myStream)); //procedure ExternalProcedure(var AStream: TStream);
end;

这是需要避免的事情吗?它会占用大量额外的内存(相关流可能会有几 MB)吗?我的猜测是否定的,但在 Delphi 中不确信。


这是需要避免的事情,因为无法保证返回的类型是正确的。 - David Heffernan
1
为什么要将内存流转换为 TStream?由于 TMemoryStream 是从 TStream 派生的,因此您可以直接传递它。实际上,所有流变体都是从 TStream 派生的原因是允许轻松统一地访问来自各种不同流类型的数据。 - SilverWarior
一个 TMemoryStream 是一个 TStream,所以强制转换甚至根本不需要。你有收到编译器错误吗?顺便说一下,如果你真的想要强制转换该值,你可以使用 "as" 运算符,它会在你要求的类型无法转换时引发异常。 - fpiette
2
@AlexV 不是的。var参数意味着被调用者可以更改引用。完全有可能库的作者不理解引用类型。这个库是什么? - David Heffernan
2
@AlexV:无论如何,您都不会复制流对象,因为Delphi中的类是引用类型,正如David所说。因此,即使您使用普通值参数(ExternalProcedure(AStream:TStream)),唯一复制的是指向流对象的指针。因此,“外部过程”仍然能够修改流对象。它唯一不能再做的事情是更改传递给它的指针。因此,如果myStream在调用之前指向$123456处的流对象,则在调用之后它仍将指向$123456。但是那里的对象可能已经发生了变化。 - Andreas Rejbrand
显示剩余4条评论
2个回答

9

MBo 正确:这种类型的强制转换只会让编译器假定指定的类型,而不会生成任何额外代码(但是在转换值类型时有很多例外情况)。

然而,我通常会避免使用这种不安全的强制转换。以下是一些可能出现的问题示例:

type
  TAnimal = class
    DNASequence: string;
  end;

  TSpider = class(TAnimal)
    MoultCount: Integer;
  end;

procedure ChangeAnimal(var AAnimal: TAnimal);
begin
  FreeAndNil(AAnimal);
  AAnimal := TAnimal.Create;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Spider: TSpider;
begin
  Spider := TSpider.Create;
  try
    Spider.DNASequence := 'CTGA...';
    Spider.MoultCount := 3;
    ChangeAnimal(TAnimal(Spider));
    ShowMessage(Spider.MoultCount.ToString); // Oops! The `TSpider` variable
                                             // points to a `TAnimal` object!
  finally
    Spider.Free;
  end;
end;

8

类型转换并不会创建新对象,也就不需要分配新的内存。它只是编译器提供类型兼容性的指令。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接