Delphi动态数组引用计数

Emm*_*oli 7 delphi

TList<integer>我决定使用而不是使用geneirc

TSolutions = array of integer;
Run Code Online (Sandbox Code Playgroud)

然后:

function TEuclidMod.gcdExtended(p, q: integer): TSolutions;
var tmpArr: TSolutions;
begin

 SetLength(tmpArr, 3);

 if (q = 0) then
  begin
   tmpArr[0] := p;
   tmpArr[1] := 1;
   tmpArr[2] := 0;
  end
 else
  begin
   vals := gcdExtended(q, modulo(p,q));
   tmpArr[0] := vals[0];
   tmpArr[1] := vals[2];
   tmpArr[2] := vals[1] - vals[2]*floor(p/q);
  end;

 Result := tmpArr;

end;
Run Code Online (Sandbox Code Playgroud)

该变量vals: TSolutions;在类中声明为private,在构造函数内部我设置了它的长度.


我在docwiki上看到动态数组被重新计算,所以我不必担心它们的生命周期.确定我写了:

constructor TEuclidMod.Create;
begin

 SetLength(vals, 3);

end;

destructor TEuclidMod.Destroy;
begin

 vals := nil;
 inherited;

end;
Run Code Online (Sandbox Code Playgroud)

到目前为止,这应该没问题; vals属于班级,我在课堂的破坏中释放它.怎么样tmpArr

我的功能正常.这tmpArr是本地的,然后我调用SetLength,我给他一个长度:如果我没错,这就是在堆上创建数组.但是当我返回时Result := tmpArr它不会被删除(tmpArr)因为函数超出了范围?我不想返回一个悬垂的指针或别的东西!我需要确定它没有被释放.

我想我是安全的,因为它是一个函数,它返回一个TSolution,所以引用计数应至少为1.这是确切的吗?基本上:即使它是本地的,它是否正确返回?

但是从我在SO上发现的,在这种情况下

procedure test;
var a: TSolution;
begin

 SetLength(a, 7);
 //do something

end;
Run Code Online (Sandbox Code Playgroud)

a始终被释放时,该过程超出范围!

J..*_*... 7

动态数组是引用计数.不要担心他们的内存管理 - 只需使用它们; 这就是引用计数的用途.您没有nil析构函数中的类字段.当对象被销毁时,编译器将删除它们的引用计数.

但是当我返回Result时:= tmpArr不会被删除(tmpArr)因为函数超出了范围?

好吧,不,因为你通过分配它来返回数组,Result并且大概是调用者依次将结果分配给一个新变量.除非调用者还没有将函数结果分配给新变量,否则引用计数自然将保持至少一个.

  • 为了完整性,动态数组是引用计数,但不遵循CopyOnWrite(COW)模式,因为`string`类型.如果修改数组的一个项目,则每个dandling复制的实例都将被修改,而对于`string`值,当你修改其中的`char`时,将分配和复制一个新的`string`实例. (2认同)