标准库优先级队列推送方法

下面的代码段是优先级队列的push方法的库实现。我想知道为什么代码行a = a[0 : n+1]不会引发超出范围的错误。


 func (pq *PriorityQueue) Push(x interface{}) {

    // Push and Pop use pointer receivers because they modify the slice's length,

    // not just its contents.

    // To simplify indexing expressions in these methods, we save a copy of the

    // slice object. We could instead write (*pq)[i].

    a := *pq

    n := len(a)

    a = a[0 : n+1]

    item := x.(*Item)

    item.index = n

    a[n] = item

    *pq = a

}


ITMISS
浏览 181回答 3
3回答

森栏

切片不是数组;它是现有阵列的视图。有问题的切片由大于其自身的数组支持。在定义现有切片的切片时,实际上是在切片基础数组,但是引用的索引是相对于源切片的。满嘴 让我们以以下方式证明这一点:我们将创建一个零长度的切片,但是我们将强制底层数组更大。使用创建切片时make,第三个参数将设置基础数组的大小。该表达式make([]int, 0, 2)将分配大小为 2 的数组,但计算结果为大小为零的切片。package mainimport ("fmt")func main() {    // create a zero-width slice over an initial array of size 2    a := make([]int, 0, 2)    fmt.Println(a)    // expand the slice.  Since we're not beyond the size of the initial    // array, this isn't out of bounds.    a = a[0:len(a)+1]    a[0] = 1    fmt.Println(a)    fmt.Println(a[0:len(a)+1])}看这里。您可以使用cap关键字来引用支持给定切片的数组的大小。您询问的特定代码cap(pq)在调用上下文中循环(container / heap / example_test.go 90行)。如果您在调用站点上修改了代码并尝试将另一个项目推送到队列中,它将如您所愿地惊慌。我...可能不会建议编写这样的代码。尽管标准库中的代码可以执行,但是如果在我的代码库中发现该代码,我会感到很酸。通常,使用append关键字更安全。

倚天杖

因为它可以在特定的示例程序中使用。这是原始/完整示例源中的重要部分)const nItem = 10和pq := make(PriorityQueue, 0, nItem)和for i := 0; i < cap(pq); i++ {&nbsp; &nbsp; &nbsp; &nbsp; item := &Item{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value:&nbsp; &nbsp; values[i],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; priority: priorities[i],&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; heap.Push(&pq, item)}

ABOUTYOU

总的来说,它确实如此。它不在container/heap示例中。这是我前一段时间给您的一般修复方法。func (pq *PriorityQueue) Push(x interface{}) {&nbsp; &nbsp; a := *pq&nbsp; &nbsp; n := len(a)&nbsp; &nbsp; item := x.(*Item)&nbsp; &nbsp; item.index = n&nbsp; &nbsp; a = append(a, item)&nbsp; &nbsp; *pq = a}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go