3

我有一个包含动态数组的记录。通常,当您将一个数组变量分配给另一个数组变量时,实际上只分配了指向该数组的指针。这意味着当您这样做时,两个变量都指向同一个数组,直到您更改其中一个变量的大小。因此,当我想将数组的单独副本分配给变量时,我使用 Copy() 函数。

但是,在这种情况下,我的数组是记录的一个字段:

  TMyRec = record
    Value: integer;
    &Array: array of integer;
  end;

当我声明两个 TMyRec 类型的变量然后将一个分配给另一个时,两个记录中的“数组”字段将指向内存中的相同地址。

为了解决这类问题,我决定重载赋值运算符,如下所示:

TMyRec = record
  Value: integer;
  &Array: array of integer;
public
  class operator Implicit(Value: TMyRec): TMyRec;
end;

class operator TMyRec.Implicit(Value: TMyRec): TMyRec;
begin
  Result := Value;
  Result.&Array := Copy(Value.&Array);
end;

如果这可行,在将 TMyRecord 变量分配给另一个变量之后,我就不必分别复制记录中的所有数组字段。

这是我所做的:

var
  Rec1, Rec2: TMyRec;
begin
  Rec1.Value := 10;
  SetLength(Rec1.Array, 1);

  //I expected the "Implicit" method to be invoked here (but it is not...)
  Rec2 := Rec1;

  //if I do that, the Rec1.Array[0] will also be changed to 1 - I don't want that to happen
  Rec2.Array[0] := 1;
end;

有没有办法让我的运算符重载按我的意愿工作?问题是我试图重载默认赋值运算符。这不可能吗?

4

3 回答 3

7

您可以将数组放在实现接口的对象实例中,并将对该接口的引用存储在记录中。这样,当您尝试通过接口(因此通过对象)分配给数组时,它可以检查其引用计数并帮助处理写时复制语义。

或者,您可以使用类型不安全的技巧来找出数组的引用计数,如果存在多个引用,则在写入之前手动复制;但如果动态数组实现发生变化,这将不受支持并且会中断。

写了如何实现一个包含在记录中的写时复制数组结构。它被实现为泛型类型,但没有什么能阻止您使用具体的数组类型,它只是不会那么通用。

于 2009-06-04T22:46:20.867 回答
3

您可以使用 TMyRec 的指针:

pMyRec = ^TMyRec;
TMyRec = record
  Value: integer;
  _Array: array of integer;
public
  class operator Implicit(Value: pMyRec): TMyRec;
end;

class operator TMyRec.Implicit(Value: pMyRec): TMyRec;
begin
  Result := Value^;
  Result._Array := Copy(Value^._Array);
end;

procedure TForm1.Button1Click(Sender: TObject);
var R1, R2 : TMyRec;
begin
  R1.Value := 1;
  SetLength( R1._Array, 2);
  R1._Array[0] := 1;
  R1._Array[1] := 2;

  R2 := @R1;
  R2._Array[0] := 3;
end;
于 2013-10-21T16:43:38.793 回答
1

不要做简单的分配。追求可读性。制作您自己的“RecCopy”程序,例如:

procedure RecCopy( const AFrom, ATo : TMyRec );
var
  I : integer;
begin
  ATo.Value := AFrom.Value;
  SetLength( ATo.Array, Length( AFrom.Array );
  For I := 0 to Length( AFrom.Array )-1 do
    ATo.Array[I] := AFrom.Array[I];
end;

请注意,您可以使用更好的方法来实现数组副本 :-) 但是您明白我的意思。

于 2009-06-05T08:43:16.887 回答