首页 文章

复制对指针或值的引用

提问于
浏览
7

我想我理解here的答案,但为了以防万一,我想明确询问以下事项(如果你认为这是同一个问题,我道歉,但对我来说,关注的问题感觉不同):

func f() *int {
  d := 6
  pD := new(int)
  pD = &d // option 1
  *pD = d // option 2
  return pD
}

我只是将引用复制为指针的第一个选项是性能方面,更优化(这是教育猜测,但似乎很明显) . 我更喜欢这种方法/模式 .

第二种选择是(浅)复制(?) . 我认为这种方法,因为它复制,我不担心GC扫描'd'的实例 . 由于我的不安全感(或作为初学者的无知),我经常使用这种方法 .

我所担心的(或更多,不安全)是在第一种方法(其中'd'的地址被转移)中,GC会认识到它('d'变量)被指针容器引用,因此它不会被扫除?因此,使用这种方法是安全的吗?即在应用程序的生命周期内,我可以安全地传递从func'f()'返回的指针'pD'吗?

参考:https://play.golang.org/p/JWNf5yRd_B

2 回答

  • 10

    没有比官方文档更好的地方了:

    func NewFile(fd int,name string)* File {
    如果fd <0 {
    返回零
    }
    f:=文件{fd,name,nil,0}
    返回&f
    }
    请注意,与C不同,返回局部变量的地址是完全可以的 . 与函数关联的存储在函数返回后仍然存在 . 实际上,获取复合文字的地址在每次评估时都会分配一个新实例,因此我们可以将这两行结合起来 .

    (来源:"Effective Go"

    因此第一个选项(返回指向局部变量的指针)绝对安全,甚至鼓励 . 通过执行escape analysis,编译器可以告诉变量转义其本地作用域并将其分配给堆 .

  • 3

    简而言之:不 .

    第一:Go中没有“引用” . 现在忘了这个想法,否则你会伤到自己 . 真 . 关于“通过引用”的思考是完全错误的 .

    第二:表现完全相同 . 暂时忘掉这种类型的纳米优化 . 特别是在处理int时 . 当且仅当您遇到性能问题时:测量,然后进行优化 . 可能直观地认为“处理8字节的小指针必须比复制具有30或甚至100字节的结构快得多” . 它不是,至少不是那么简单 .

    第三:只需写一个 func f() *int { d := 6; return &d; } . 这里没有必要做任何花哨的舞蹈 .

    第四:选项2对int进行“深层复制” . 但这可能会产生误导,因为没有int的“浅层副本”所以我不确定我是否理解你在这里问的是什么 . Go没有深层和浅层副本的概念 . 如果复制指针值,则复制指针值 . 你还记得第一点吗? Go中没有引用 . 指针值是一个值,如果复制,您有一个指针值的副本 . 这样的副本对指向的值绝对没有任何意义,特别是它不会复制 . 这会暗示Go中的副本不是“深度” . 在谈论Go时,忘记深/浅拷贝 . (当然,您可以实现执行自定义对象“深层复制”的功能)

    第五:Go有一个正常工作的垃圾收集器 . 你所做的事情完全没有区别:当一个物体存在时,它将不被收集,一旦它被收集,它就会被收集 . 您可以传递,返回,复制,移交,获取地址,取消引用指针或任何您喜欢的内容,这无关紧要 . GC正常工作 . (除非你故意通过使用包不安全来寻找疼痛和错误 . )

相关问题