Delphi TBytes - 如何复制?

时间:2011-02-09 07:48:25

标签: arrays delphi

点在这里是唯一的。

现在:

type TSomeClass=class(TObject)
  private
    DataWrite: TBytes;
  ...
end;

Function TSomeClass.GetPacket: TBytes;
begin
  SetLength(Result, Length(DataWrite));
  Move(DataWrite[0],Result[0],Length(DataWrite));
end;

我想要实现的目标:

Function TSomeClass.GetPacket: TBytes;
begin
  Result := DataWrite;
end;

因为Delphi中的数组是指向第一个元素的指针,后者只能写入4个字节,所以它的速度要快得多。这是对的吗?

2 个答案:

答案 0 :(得分:7)

您需要注意的一点是,与字符串不同,动态数组不是“写时复制”。

如果指定字符串或动态数组,则只复制堆上数据的指针并增加引用计数。

但是使用字符串,如果你然后写入一个字符串(例如s [1]:='a'),其引用计数> 1,编译器将发出代码,确保首先复制字符串。动态数组不是这种情况:

var 
  s, t: string;
  a, b: TBytes;
begin
  s := 'abc';
  t := s;
  t[2] := 'X';
  WriteLn(s); //still abc

  a := TBytes.Create(1, 2, 3);
  b := a;
  b[1] := 0;
  WriteLn(a[1]); // is now 0 not 2!

因此,对于您的代码,如果在调用GetPacket后更改DataWrite的内容,则更改将在GetPacket返回的TBytes中可见。

对于实际制作数组副本的代码,您可以使用:

而不是调用SetLength And Move。
function TSomeClass.GetPacket: TBytes;
begin
  Result := Copy(DataWrite, 0, High(Integer));
end;

答案 1 :(得分:2)

这将有效,但请注意,您现在正在调用GetPacket的客户端代码中的相同字节数组。这可能是一个坏主意。考虑一些网络库,它对字节数组进行一些额外的压缩或加密。这会产生很多可能与你的类进行交互而不使用暴露的接口 - 这很糟糕。因此,恕我直言复制是更好的选择。

BTW:我们在这里谈论的数组有多大?