【问题标题】:How array type assignment works?数组类型分配如何工作?
【发布时间】:2015-01-30 21:10:29
【问题描述】:

我有以下代码:

type
  PSuperListItem = ^TSuperListItem;
  TSuperListItem = record
    SubItems  : array of String;
    Marked    : Boolean;
    ImageIndex: Integer;
  end;

  TSuperListItems = array of PSuperListItem;

  TMyList = class(TCustomControl)
  public
   Items, ItemsX : TSuperListItems;
   procedure SwapItemLists;
  end;

procedure TMyList.SwapItemLists;
var tmp:TSuperListItems;
begin
 tmp:=Items; Items:=ItemsX; ItemsX:=tmp;
end;

我想知道我是否正确地完成了来自SwapItemLists 的断言。当我将 Items 分配给 tmp 时会发生什么?将创建Items 的新副本还是仅传递该变量的指针?

【问题讨论】:

    标签: arrays delphi variable-assignment


    【解决方案1】:

    动态数组是引用类型。这意味着您只是交换了引用。不会复制数组的内容。

    能够自己回答此类问题的关键是了解作为引用类型的意义。在动态数组的情况下,动态数组类型的变量保存对数组的引用。这是通过动态数组变量作为指向数组的指针在幕后实现的。

    考虑这段代码:

    var
      a, b: TArray<Integer>;
    ....
    a := TArray<Integer>.Create(42);
    b := a;
    b[0] := 666;
    Assert(a[0] = 666);
    Assert(@a[0] = @b[0]);
    

    在这段代码中,只有一个数组。 ab 两个变量都引用了该数组的同一个实例。

    要制作动态数组的副本,请使用System 单元中的Copy 函数。

    引用类型的其他示例包括类实例变量、接口变量、匿名方法和字符串。除了字符串之外,它们的行为都类似于动态数组。

    字符串实现写时复制。这意味着如果一个字符串对象有多个对它的引用,则通过引用进行的修改会导致在修改点进行复制。这具有使字符串数据类型在语义上表现得像值类型的效果。实际上,当您对字符串使用赋值时,该赋值在语义上与复制没有区别。但是作为优化,复制字符串的实际实现被推迟到需要它时。

    【讨论】:

    • 也许是吹毛求疵,但我认为您关于字符串分配的陈述可能会让未来的读者感到困惑:您说分配是通过复制字符串来执行的,然后您继续将复制推迟到需要时。所以,未来的读者可能想知道这个字符串是什么时候真正被复制的。
    • @iamjoosy 公平点。我试了一个词。我想要得到的是,从程序员的角度来看,字符串表现得好像它们是值,但实现是用 COW 引用的。从广义上讲,您不需要了解实现,如果您将字符串视为值,那么您的心智模型将匹配行为。
    猜你喜欢
    • 2019-02-24
    • 2014-03-15
    • 1970-01-01
    • 2011-01-03
    • 2021-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多