【发布时间】:2017-08-30 11:02:58
【问题描述】:
我决定使用而不是使用通用 TList<integer>
TSolutions = array of integer;
然后:
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;
变量vals: TSolutions;在类中被声明为私有,在构造函数中我正在设置它的长度。
我在 docwiki 上读到动态数组是 ref 计数的,所以我不必担心它们的生命周期。可以肯定的是我已经写了:
constructor TEuclidMod.Create;
begin
SetLength(vals, 3);
end;
destructor TEuclidMod.Destroy;
begin
vals := nil;
inherited;
end;
到目前为止,这应该没问题; vals 属于班级,我在班级销毁时将其释放。 tmpArr 呢?
我的功能正常工作。 tmpArr 是本地的,然后我调用 SetLength 并给他一个长度:如果我没记错的话,这是在堆上创建数组。但是当我返回 Result := tmpArr 时,由于函数超出范围,它不会被删除(tmpArr)吗?我不想返回一个悬空指针或其他东西!我需要确保它没有被释放。
我想我是安全的,因为它是一个函数,它返回一个 TSolution,因此引用计数至少应该始终为 1。准确吗?基本上:即使是本地的,是否正确返回?
但是根据我在 SO 上的发现,在这种情况下
procedure test;
var a: TSolution;
begin
SetLength(a, 7);
//do something
end;
当过程超出范围时,a 总是被释放!
【问题讨论】:
-
你可以放弃 tmpArr。不要声明它并直接使用 Result 。在析构函数中将 vals 设置为 nil 也是毫无意义的。 le 析构函数无论如何都会这样做,没有必要重复两次。
-
使用
TArray<Integer>也更有意义,因为它具有更灵活的类型兼容性。和 SetLength(vals, 3);完全浪费了,因为您稍后会覆盖 vals。你有相当的理解不足,你没有意识到。 -
说了这么多,你根本不应该使用动态数组。它应该是具有三个字段的记录,或者可能是长度为 3 的非动态数组。我认为记录是正确的选择。然后你可以命名这些字段。
-
@DavidHeffernan 好的,谢谢您的建议!该函数只是一个重载,因为我想尝试动态数组方式(事实上我已经要求解决一个疑问)。我更喜欢的是过程 getSolutions(aList: TList
); -
@EmmaRossignoli
TList<integer>感觉像是这个应用程序的一个沉重的容器,特别是如果您不需要使用TList添加的任何功能或好处。就像大卫说的那样,记录可能是一个更好的容器 - 更轻,堆栈分配为局部变量,在分配时复制(这符合您在这里的使用模式)并且您可以获得命名字段的好处,这使您的代码更具可读性。
标签: delphi