Golang Pointer反向链接列表混乱

时间:2018-04-26 22:19:52

标签: pointers go linked-list

我是Golang的新手,对于指针的工作方式我有点困惑,我正在使用反向链接列表问题作为示例。

func reverseList(head *ListNode) *ListNode {
  var prev *ListNode = nil
  for {
    if head == nil {
      break
    }
    temp := head
    head = head.Next
    temp.Next = prev
    prev = temp
  }
    return prev
}

在这种情况下,temphead指向相同的内存位置。但是,如果我将temp.Next = prev行放在head = head.Next之前,head.Next将指向零。

当我们说temp.Next = prev时,幕后发生了什么。我们是说结构temp指向的是现在已更改,因此如果我将该行放在head = head.Next之上,那么head现在也指向此更改的结构?

我认为为了改变head.Next的实际价值,我们必须取消引用它?

我有点困惑,为什么这不起作用

func reverseList(head *ListNode) *ListNode {
  var prev *ListNode = nil
  for {
    if head == nil {
      break
    }
    temp := head   
    temp.Next = prev
    prev = temp
    head = head.Next <--- CHANGED ORDERING HERE
  }
    return prev
}

1 个答案:

答案 0 :(得分:1)

它不起作用,因为你在第一次迭代时使head无效。这是流程:

temp := head   
// Since temp is a pointer, any modifications made to it will also
// impact head. So when you set temp.Next here, you're also setting
// head.Next. Since prev is always nil on the first iteration, you've
// set head.Next = nil.
temp.Next = prev
prev = temp
// This will set head to nil, always.
head = head.Next

在正确的版本中,在发生任何写入之前更新head = head.Next意味着您已经转移到下一个元素,因此可以安全地覆盖该值。

实际上,第二个版本所做的就是剪掉除第一个版本之外的所有列表元素。如果在调用此函数之前没有引用第二个元素,那么它们现在处于不稳定状态并且将被垃圾收集。

根据评论更新:
当您执行temp := head之类的操作时,您会说“创建一个名为temp的指针,并将其指向head指向的同一事物。”如果您随后修改temp指向的内容(例如,执行temp.Next = prev),您还会在读取head指向的数据时看到更改,因为它仍然指向在同一个地方。

当您执行head = head.Next时,您说“更新head指向head.Next指向的任何地方”。这会更新head本身而不是其指向的数据,因此您不会看到与temp相关的任何更改。

这是了解有关指针的更多资源:https://dave.cheney.net/2017/04/26/understand-go-pointers-in-less-than-800-words-or-your-money-back