取消引用结构会返回结构的新副本吗?

Posted

技术标签:

【中文标题】取消引用结构会返回结构的新副本吗?【英文标题】:Does dereferencing a struct return a new copy of struct? 【发布时间】:2016-11-21 10:51:23 【问题描述】:

为什么当我们使用 (*structObj) 引用结构时,Go 似乎返回了 structObj 的新副本,而不是返回原始 structObj 的相同地址?这可能是我的一些误解,所以我寻求澄清

package main

import (
    "fmt"
)

type me struct 
    color string
    total int


func study() *me 
    p := me
    p.color = "tomato"
    fmt.Printf("%p\n", &p.color)
    return &p


func main() 
    p := study()
    fmt.Printf("&p.color = %p\n", &p.color)

    obj := *p
    fmt.Printf("&obj.color = %p\n", &obj.color)
    fmt.Printf("obj = %+v\n", obj)

    p.color = "purple"
    fmt.Printf("p.color = %p\n", &p.color)
    fmt.Printf("p = %+v\n", p)
    fmt.Printf("obj  = %+v\n", obj)

    obj2 := *p
    fmt.Printf("obj2 = %+v\n", obj2)

输出

0x10434120
&p.color = 0x10434120
&obj.color = 0x10434140   //different than &p.color!
obj = color:tomato total:0
p.color = 0x10434120
p = &color:purple total:0
obj  = color:tomato total:0
obj2 = color:purple total:0 // we get purple now when dereference again

Go playground

【问题讨论】:

【参考方案1】:

tl;dr 在 Go 中解引用(使用 * 运算符)不会复制。它返回指针指向的值。

【讨论】:

没错,虽然作业确实复制了! (请注意,对于切片和映射,它只会复制标头值,而不是实际元素,因此看起来好像没有复制)【参考方案2】:

当你写作时

obj := *p

您正在复制p 指向的结构的值(* 取消引用p)。它类似于:

var obj me = *p

所以objme 类型的新变量,被初始化为*p 的值。这会导致obj 具有不同的内存地址。

注意objme 类型,而p*me 类型。但它们是不同的值。更改obj 字段的值不会影响p 中该字段的值(除非me 结构中有一个引用类型作为字段,即切片、映射或通道。参见here和here.)。如果您想产生这种效果,请使用:

obj := p
// equivalent to: var obj *me = p

现在obj 指向与p 相同的对象。它们本身仍然有不同的地址,但在它们内部保存的是实际 me 对象的相同地址。

【讨论】:

有没有办法获得指向 p 的相同的取消引用指针?就像在 main() 函数中一样,如果我们将结构附加为切片,我们将始终必须在附加本身内部取消引用它,即 res = append(res, *p)。 这不仅仅是“创建”一个新变量,通过取消引用分配给现有变量会复制值,例如*a = *b 仍将 *b 复制到 *a @jimB yap,有没有办法避免重复复制?因为基本上操作只需要处理相同的 p 结构。 @ken:我不明白你的意思。您需要某种值,因此它要么是结构值,要么是指针值。如果要引用相同的结构或避免复制,请使用指针。 @JimB 好吧,也许我想太多了;)我明白你的意思,谢谢你的回复!【参考方案3】:

不,“赋值”总是在 Go 中创建一个副本,包括对函数和方法参数的赋值。语句obj := *p*p 的值复制到obj

如果您将语句 p.color = "purple" 更改为 (*p).color = "purple",您将获得相同的输出,因为取消引用 p 本身不会创建副本。

【讨论】:

其实是c背景,这让我很困惑。谢谢,认为这两个答案都是正确的,并且几乎在同一时间联系到我,因此选择了更多详细信息,但也为您的答案投票! dereferencing p itself does not create a copy 这澄清了我的困惑,谢谢

以上是关于取消引用结构会返回结构的新副本吗?的主要内容,如果未能解决你的问题,请参考以下文章

返回对本地取消引用的指针的引用

取消引用指针会复制它吗?

每次访问数组时,C 都会复制元素吗?

在 ActivateAsync 上取消服务结构参与者激活?

我可以以任何方式从 OpenCV 对象取消引用中将数据分配给双重函数返回检索吗?

取消设置 php 参考