你能重载 Delphi 记录的赋值运算符吗?
我有一个包含动态数组的记录。 正常情况下,当您将一个数组变量分配给另一个数组变量时,实际上只分配了指向该数组的指针。 这意味着当您这样做时,两个变量都指向同一个数组,直到您更改其中一个变量的大小。 因此,当我想将数组的单独副本分配给变量时,我使用 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;
有没有办法让我的操作员重载按我想要的方式工作? 问题是我试图重载默认的赋值运算符。 这不可能吗?
I have a record that contains a dynamic array. It is normal that when you assign one array variable to another, in fact only the pointer to that array is assigned. This means that when you do that, both the variables point to the same array until you change the size of one of them. Therefore, when I want to assign a separate copy of an array to a variable, I use the Copy() function.
In this case, however, my array is a field of a record:
TMyRec = record
Value: integer;
&Array: array of integer;
end;
When I declare two variables of type TMyRec and then assign one to another, the "Array" fields in both of the records will be pointing to the same address in memory.
To solve that sort of problem I decided to overload the assign operator as follows:
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;
If this worked, I wouldn't have to copy all array fields in my records separately after assigning TMyRecord variables one to another.
Here is what I do:
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;
Is there a way to make my operator overload work as I want it to? The thing is that I'm trying to overload the default assignment operator. Isn't that possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以将数组放入实现接口的对象实例中,并将对该接口的引用存储在记录中。 这样,当您尝试通过接口(从而通过对象)分配给数组时,它可以检查其引用计数并帮助实现写时复制语义。
或者,您可以使用类型不安全的技巧来找出数组的引用计数,如果存在多个引用,则在写入之前手动复制; 但这将不受支持,并且如果动态数组实现发生变化就会中断。
我写了如何实现包裹在记录中的写时复制数组结构。 它是作为通用类型实现的,但没有什么可以阻止您使用具体的数组类型,只是它不会那么通用。
You could put your array inside an object instance which implements an interface, and store a reference to that interface inside the record. That way, when you try to assign to the array via the interface (and thus via the object), it can check its reference count and help with copy-on-write semantics.
Alternatively, you could use type-unsafe tricks to find out the reference count of the array, and manually copy before write if multiple references exist; but that would be unsupported and would break if the dynamic array implementation changed.
I wrote up how to implement a copy-on-write array structure wrapped up in a record. It's implemented as a generic type, but nothing stops you from using a concrete array type instead, it just won't be as general.
您可以使用 TMyRec 的指针:
You can use a pointer of TMyRec :
不要做简单的分配。 追求可读性。 制作您自己的“RecCopy”过程,如下所示:
请注意,您可以使用更好的方法来实现数组复制:-)
但你明白我的意思。
Dont do a simple assign. Go for readability. Make your own 'RecCopy' procedure like:
Note that you can use a better way of implmenting the array copy :-)
But you see my point.