鉴于以下情况:
LBytes: TBytes;
LArr: array[1..512] of Byte;
...
SetLength(LBytes, 512);
将所有字节从 LBytes 复制到 LArr 的正确 Move() 调用是什么?
Move(LBytes[0], LArr, Length(LBytes)); // works
Move(LBytes[0], LArr[1], Length(LBytes)); // works, too
Move(LBytes, LArr[1], Length(LBytes)); // fail
有人可以解释为什么使用 Larr 和 Larr[1] 没有区别,但在 LBytes[0] 和 LBytes 之间有区别吗?
最佳答案
那是因为 LBytes
是一个动态数组,它最终是指向该数组的指针。另一方面,LArr
是数组。
另一种说法是动态数组是引用类型,而定长数组是值类型。
在我的书中,有两种可行的方法可以做到这一点:
Assert(Length(LBytes)<=Length(LArr));
Move(LBytes[0], LArr, Length(LBytes));
或者
Assert(Length(LBytes)<=Length(LArr));
Move(Pointer(LBytes)^, LArr, Length(LBytes));
我更喜欢后者,因为当启用范围检查时,它对零长度数组具有弹性。在这种情况下,第一个代码块会导致运行时范围检查错误。
您可能也有动力避免这种低级的诡计。我有一个 utility class 允许我写:
TArray.Move<Byte>(LBytes, LArr);
该方法的签名是:
class procedure Move<T>(const Source: array of T; var Dest: array of T); overload; static;