gpt4 book ai didi

delphi - 记录中的动态数组引用计数

转载 作者:行者123 更新时间:2023-12-03 18:37:16 26 4
gpt4 key购买 nike

我有一个带有动态数组字段的advanced record
记录具有用于连接记录和字节的class operator。也是一个Add方法,添加一个字节。

对于我将要使用的记录,动态数组字段的引用计数非常重要。当运行下面的两个测试过程时,您可以看到串联的引用计数为2,而add方法的引用计数为1。

program TestReferenceCount;

{$APPTYPE CONSOLE}

uses
System.SysUtils;

Type
TRec = record
class operator Add(const a: TRec; b: Byte): TRec;
private type
PDynArrayRec = ^TDynArrayRec;
TDynArrayRec = packed record
{$IFDEF CPUX64}
_Padding: LongInt; // Make 16 byte align for payload..
{$ENDIF}
RefCnt: LongInt;
Length: NativeInt;
end;
private
FArr: TBytes;
function GetRefCnt: Integer;
public
procedure Add(b : Byte);
property RefCnt: Integer read GetRefCnt;
end;

procedure TRec.Add(b : Byte);
var
prevLen: Integer;
begin
prevLen := System.Length(Self.FArr);
SetLength(Self.FArr, prevLen + 1);
Self.FArr[prevLen] := b;
end;

class operator TRec.Add(const a: TRec; b: Byte): TRec;
var
aLen: Integer;
begin
aLen := System.Length(a.FArr);
SetLength(Result.FArr, aLen + 1);
System.Move(a.FArr[0], Result.FArr[0], aLen);
Result.FArr[aLen] := b;
end;

function TRec.GetRefCnt: Integer;
begin
if Assigned(FArr) then
Result := PDynArrayRec(NativeInt(FArr) - SizeOf(TDynArrayRec)).RefCnt
else
Result := 0;
end;

procedure TestConcatenation;
var
r1 : TRec;
begin
WriteLn('RC:', r1.RefCnt); // <-- Writes 0
r1 := r1 + 65;
WriteLn('RC:', r1.RefCnt); // <-- Writes 2
end;

procedure TestAdd;
var
r1 : TRec;
begin
WriteLn('RC:', r1.RefCnt); // <-- Writes 0
r1.Add(65);
WriteLn('RC:', r1.RefCnt); // <-- Writes 1
end;

begin
TestConcatenation;
TestAdd;
ReadLn;
end.


当记录变量超出范围时,编译器将处理额外的引用计数,因此在这一点上确实没有问题。

但是可以解释这种行为吗?它是未记录的实现细节吗?有办法避免多余的计数吗?

最佳答案

让我们看一下这个函数:

procedure TestConcatenation;
var
r1 : TRec;
begin
r1 := r1 + 65;
end;


编译器实际上是这样实现的:

procedure TestConcatenation;
var
r1 : TRec;
tmp : TRec;
begin
tmp := r1 + 65;
r1 := tmp;
end;


编译器引入了一个临时本地变量来存储 r1 + 65的结果。有一个很好的理由。如果没有,它将在哪里写您的加法运算符的结果?由于最终目标是 r1,因此,如果您的加法运算符直接写入 r1,它将修改其输入变量。

无法停止编译器生成此临时本地。

关于delphi - 记录中的动态数组引用计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17032741/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com