为了账号安全,请及时绑定邮箱和手机立即绑定

为什么交换成员函数不需要使用指针?

为什么交换成员函数不需要使用指针?

Go
一只名叫tom的猫 2022-08-15 10:00:37
我是Golang的新手。当我尝试实现我的第一个优先级队列时,我发现 Push and Pop 函数需要使用成员的指针,但 Swap 不需要。我知道,如果您在成员函数中使用指针,则意味着您可以更改实例本身而不是其副本。但是,为什么 Swap 可以使用副本而不是指针呢?type maxHeap []intfunc (max maxHeap) Len() int {    return len(max)}func (max maxHeap) Less(a, b int) bool {    return max[a] > max[b]}func (max maxHeap) Swap(a, b int) {    max[a], max[b] = max[b], max[a]}func (max *maxHeap) Push(a interface{}) {    *max = append(*max, a.(int))}func (max *maxHeap) Pop() interface{} {    x := (*max)[len(*max)-1]    *max = (*max)[0 : len(*max)-1]    return x}
查看完整描述

2 回答

?
FFIVE

TA贡献1797条经验 获得超6个赞

尝试这个练习:使用指针接收器编写所有函数。在每个函数中,获取顶部指针的当前值,直到需要更改通过指针存储的值为止。


因此,和 分别变为:SwapPush


func (p *maxHeap) Swap(a, b int) {

    max := *p

    max[a], max[b] = max[b], max[a]

}

func (p *maxHeap) Push(a interface{}) {

    max := *p

    *p = append(max, a.(int))

}

根据需要对其他函数重复上述步骤。


现在,返回每个转换后的函数。哪些人为 *p 分配了新值?哪些函数从不分配新值,而只是继续使用 max?


当你回答这个问题时,你应该发现自己开悟了。


旁注:由于立即转换为,它可能应该采取.同样,应该只是返回。或者,请参阅标准容器/堆包。PushaintintPopint


查看完整回答
反对 回复 2022-08-15
?
红颜莎娜

TA贡献1842条经验 获得超12个赞

原因在于,在您的情况下,切片确实是一个指针。切片由指向基础内存的指针、该内存的当前长度和总容量组成。这意味着切片实际上是具有以下三个要素的数据结构:[]int

  1. 内存指针

  2. 长度

  3. 能力

你可以把它想象成一个

type slice struct {
    data     unsafe.Pointer
    length   int
    capacity int}

现在,当您调用它时,它将切片作为输入,并返回切片作为输出。append

如果输入切片有足够的容量来添加新元素,则将其更改到位(append是一个特殊的内置函数,它不需要切片指针作为输入,无论如何它都会更改切片)。

如果输入切片没有添加新项的能力,则会创建一个具有足够容量的新切片,将旧切片复制到其中,然后在最后添加新数据。然后返回此新切片。

在您的情况下,您希望更改函数中的堆。该函数可能会返回一个新切片,您必须用它覆盖现有切片。这意味着您需要指向切片的指针,因为您要替换切片结构。Pushappend

在 and 函数中,您可以更改切片的内容,而不是切片数据结构本身。您可以使用切片包含的内存指针访问切片中的数据。这意味着这些函数使用切片数据结构的副本,但切片数据结构的原始副本和副本都指向同一基础内存。切片引用的内存是相同的。由于您不在此处调用 append,因此不需要更新切片本身。SwapLess

在函数中,您再次更改切片数据结构,因为您更改了其长度字段。这就是为什么您需要一个指向此处切片的指针。Pop


查看完整回答
反对 回复 2022-08-15
  • 2 回答
  • 0 关注
  • 111 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信