【问题标题】:Why changing copy of pointer does not affect the initial object为什么更改指针副本不会影响初始对象
【发布时间】:2020-09-22 00:24:03
【问题描述】:

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

}

【问题讨论】:

    标签: pointers go


    【解决方案1】:

    currenti3 都是指针。

    current:= i3
    

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

    指针的副本与它的复制没有任何关系,只是两者都指向相同的值。所以修改currenti3没有任何影响。

    你可以用这种方式做到这一点

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

    现在currenti3的指针,现在如果你改变当前指向的值会影响i3

    【讨论】:

      【解决方案2】:

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

      current := i3
      

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

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

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

      【讨论】:

        【解决方案3】:

        在第一个示例中,您创建了一个指针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}   
        

        在第二种情况下,您执行相同的操作,但现在您更改了存储在 i3 指针中的地址,而不是 current 指针。 如果您遵循迭代:

        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})

        【讨论】:

          猜你喜欢
          • 2021-04-01
          • 2019-09-15
          • 2020-08-09
          • 1970-01-01
          • 2011-09-30
          相关资源
          最近更新 更多