【问题标题】:Resizing of slices - whether to check for `len(slice) > 1` or `newCap > 2*len(slice)`调整切片的大小 - 是否检查 `len(slice) > 1` 或 `newCap > 2*len(slice)`
【发布时间】:2020-11-10 09:12:27
【问题描述】:

Go Programming Language 一书中,作者给出了以下append() 函数的代码示例,该函数接受[]intint 作为参数,并将相应地处理调整大小:

// gopl.io/ch4/append
func appendInt(x []int, y int) []int {
    var z []int
    zlen := len(x) + 1
    if zlen <= cap(x) {
        // There is room to grow. Extend the slice.
        z = x[:zlen]
    } else {
        // There is insufficient space. Allocate a new array.
        // Grow by doubling, for amortized linear complexity.
        zcap := zlen
        if zcap < 2*len(x) { // Question: Why not len(x) > 1?
            zcap = 2 * len(x)
        }
        z = make([]int, zlen, zcap)
        copy(z, x)
    }
    z[len(x)] = y
    return z 
}

问题

为什么最里面的支票写成if zcap &lt; 2*len(x),而不是等价的if len(x) &gt; 1

后者对我来说似乎更清楚,并表明如果初始切片的长度为 0 或 1,我们不会在添加新元素后分配额外的容量。

zcap &lt; 2*len(x)len(x) &gt; 1 等价的详细信息

我们可以看到zcap的值是从zlen赋值的,而len(x) + 1的值又是len(x) + 1,所以如果我们安排不等式:

zcap

代入zcap := zlen后,我们得到:

zlen

代入zlen := len(x) + 1后,我们得到:

len(x) + 1

重新排列后,我们得到:

len(x) > 1

【问题讨论】:

  • zcap &lt; 2*len(x) 条件对我来说毫无意义。实际上,您只有一个极端情况:len(x) == 0,其他一切都可以用newCapacity = len(x) * 2处理
  • zcap 1。您的推导是错误的,因为 len(x) 可以为 0。(可能还有很多其他错误。)
  • @Volker 为什么 zcap 1?
  • @Volker,推导有效。如果 len(x)>1,该代码基本上将容量加倍,但由于某种原因,它用很多词来做到这一点。请注意,此时 len(x)==cap(x),并且仅当 len(x)=0 时才不必将容量翻倍。
  • A,对不起,它不是被零除。我的错。

标签: go slice


【解决方案1】:

你说得对,zcap &lt; 2*len(x) 等价于len(x) &gt; 1。在此函数中,您完全可以将 zcap &lt; 2*len(x) 替换为 len(x) &gt; 1

但根据来源code,还有另一个函数名为appendslice。在这个函数中,你不能做替换。

我认为作者使用zcap &lt; 2*len(x) 只是为了保持两个功能一致。这里的主要目的是避免频繁分配。

【讨论】:

    猜你喜欢
    • 2015-07-24
    • 2019-12-27
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多