【问题标题】:How much information do array variables share?数组变量共享多少信息?
【发布时间】:2012-02-06 03:19:56
【问题描述】:

当我将一个数组变量分配给另一个数组变量时,复制/共享了多少信息?

int[] a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
int[] b = a;
a[0] = 42;
writefln("%s %s", a[0], b[0]);   // 42 42

显然,ab 共享相同的有效载荷,因为 42 被打印了两次。

a ~= 10;
writefln("%s %s", a.length, b.length);   // 11 10

附加到a 不会改变b,所以长度似乎不是有效载荷的一部分?

b = a;
a ~= 11;
b ~= 42;
writefln("%s %s", a[11], b[11]);   // 11 42

符合标准的 D 实现是否也可以打印 42 42b ~= 42可以覆盖a里面的11吗?

ab 究竟是什么时候相互分离的? D 在后台执行一些 COW 吗?

【问题讨论】:

    标签: arrays variable-assignment d sharing deep-copy


    【解决方案1】:

    array variables in D are equivalent to

    struct array!T{
        size_t length;
        T* ptr;
    
    }
    

    (加上索引和切片的实现)

    追加的特殊之处在于它可以保留原始切片并追加到末尾。仅当数组的 capacity 足够大或 realloc 可以就地扩展时才会发生这种情况

    这些最后的东西都保存在 GC 中

    【讨论】:

      【解决方案2】:

      D 中的“数组”实际上并不存在。

      Slices do.

      切片只是一个指针和一个长度。因此,当您将它们相互分配时,指针和长度会被复制。如果您修改目标数据,那么它将在切片的所有实例中可见 - 但如果您放大一个切片,另一个切片仍将使用其旧长度。

      您通常不能“缩小”内存中数组的实际长度(尽管您当然可以减少切片的长度,因此它“看到”的数据更少),所以这不会导致问题。

      希望能解释发生了什么。

      【讨论】:

      • 那么~= 总是具有线性复杂度吗?我的印象是,重复调用 ~= 会比二次函数执行得更好......
      • @FredOverflow:是的,它是线性的——如果可能的话,它确实会附加到原始数组,但由于旧切片只能“看到”原始部分(通过它自己的长度副本),那么它不会看到你附加了任何东西。
      • 所以~= 只有在不发生共享的情况下才有效?这意味着b = a 在后台以某种方式修改了a,对吧?
      • @FredOverflow:不,它很有效——如果数组末尾有空间(“T 数组”=“内存中的实际数据”;“切片”=T[]=“引用数组”),然后它就地追加并增加切片的长度。如果没有(例如,如果 其他人 通过附加到该切片的另一个副本而用完该房间),然后 它复制数据。 (b = a 确实 not 在后台修改 a - 这是一个简单的指针分配。唯一的问题是,如果您附加到 b,那么附加到 a 会导致重新分配——这仍然是线性时间,因为它只发生一次。)
      • 我想我现在要停止争论并开始阅读您链接到的文章:)
      猜你喜欢
      • 2014-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-11
      • 1970-01-01
      • 1970-01-01
      • 2016-08-14
      • 2021-09-23
      相关资源
      最近更新 更多