我学会处理指针, 在这个例子中,我不明白为什么 将i3重新分配给新的当前对象并执行操作current = current.next不会影响i3对象。但是,使用了相同的地址
func main() {
i := &Node{data: 1}
i2 := &Node{data: 2, next: i}
i3 := &Node{data: 3, next: i2}
current := i3
for current.next != nil {
current = current.next
}
log.Println(current)
log.Println(i3)
/*
2020/06/03 12:19:23 &{1 <nil>}
2020/06/03 12:19:23 &{3 0xc42000e1f0}
*/
}
type Node struct {
data int
next *Node
}
而如果我不使用i3对象的副本,则该对象会在循环中得到很好的修改
func main() {
i := &Node{data: 1}
i2 := &Node{data: 2, next: i}
i3 := &Node{data: 3, next: i2}
log.Println(i3)
/*
2020/06/03 12:22:05 &{3 0xc42000e1f0}
*/
for i3.next != nil {
i3 = i3.next
}
log.Println(i3)
/*
2020/06/03 12:22:05 &{1 <nil>}
*/
}
答案 0 :(得分:2)
在您的第一个示例中,简短的变量声明:
current := i3
创建一个名为current
的指针类型的新变量。它是与i3
不同的变量,但是具有相同的指针值。
该循环仅修改(分配给)current
变量,因此存储在i3
中的指针永远不会改变。因此,在循环之后,i3
仍指向带有data = 3
的节点,并且current
将是最后一个,即带有data = 1
的节点。
在第二个示例中,您没有创建current
变量,而是修改了(分配给)i3
变量。因此,循环之后它将指向带有data = 1
的最后一个节点。在这两种情况下,都不会修改节点对象,只会修改current
或i3
变量。
答案 1 :(得分:2)
current
和i3
都是指针。
current:= i3
复制指针意味着现在current
将指向i3
指向的地址。
一个指针的副本与被复制的指针没有任何关系,只是两个指针指向相同的值。因此,修改current
对i3
无效。
您可以通过这种方式完成
current := &i3
for (*current).next != nil {
*current = (*current).next
}
现在current
是i3
的指针,现在,如果您更改将影响i3
的当前指针值。
答案 2 :(得分:1)
在第一个示例中,创建一个指针current
,该指针将具有与i3
相同的值(结构Node{data: 3, next: i2}
的地址)。
在for循环中执行current = current.next
语句时,仅更改指针的值,而不更改地址后面的值。您只需替换指针中存储的地址即可。
如果您遵循迭代:
0., current -> Node{data: 3, next: i2}
1., current -> Node{data: 2, next: i}
2., current -> Node{data: 1}
其他指针将保持不变。
i -> Node{data: 1}
i2 -> Node{data: 2, next: i}
i3 -> Node{data: 3, next: i2}
在第二种情况下,您执行相同的操作,但是现在更改了存储在current
指针中的地址,而不是i3
指针。
如果您遵循这些迭代:
0., i3 -> Node{data: 3, next: i2}
1., i3 -> Node{data: 2, next: i}
2., i3 -> Node{data: 1}
其他指针将保持不变。
i -> Node{data: 1}
i2 -> Node{data: 2, next: i}
当然,您将在内存中某处有一个对象,而无法访问它(Node {data:3,next:i2})