为什么更改指针副本不会影响初始对象

时间:2020-06-03 10:24:23

标签: pointers go

我学会处理指针, 在这个例子中,我不明白为什么 将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>}
        */

}

3 个答案:

答案 0 :(得分:2)

在您的第一个示例中,简短的变量声明:

current := i3

创建一个名为current的指针类型的新变量。它是与i3不同的变量,但是具有相同的指针值。

该循环仅修改(分配给)current变量,因此存储在i3中的指针永远不会改变。因此,在循环之后,i3仍指向带有data = 3的节点,并且current将是最后一个,即带有data = 1的节点。

在第二个示例中,您没有创建current变量,而是修改了(分配给)i3变量。因此,循环之后它将指向带有data = 1的最后一个节点。在这两种情况下,都不会修改节点对象,只会修改currenti3变量。

答案 1 :(得分:2)

currenti3都是指针。

current:= i3

复制指针意味着现在current将指向i3指向的地址。

一个指针的副本与被复制的指针没有任何关系,只是两个指针指向相同的值。因此,修改currenti3无效。

您可以通过这种方式完成

current := &i3
for (*current).next != nil {
    *current = (*current).next
}

现在currenti3的指针,现在,如果您更改将影响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})

相关问题