【问题标题】:Const reference in C++ and equivalent in GolangC++ 中的 const 引用和 Golang 中的等价物
【发布时间】:2016-05-08 01:20:10
【问题描述】:

我来自 C++ 世界和 C++,通常当您关心性能并且不需要更改对象时,您使用常量引用传递它

void func(const std::string& str)

在这种情况下,字符串没有被复制,不能在函数中修改。

我知道,在 Go 中有两种传递对象的方法:

  • 按值,然后你不能修改(或者实际上你可以但没有意义)它,但它非常消耗内存
  • 通过指针,这从内存的角度来说是好的,但是你可以修改对象。

那么,最好的方法是什么?即使您不想修改它,也总是通过指针传递对象,因为它更快?或者有一些编译器优化,即使你按值发送它有时也会作为参考发送?

【问题讨论】:

标签: go


【解决方案1】:

Go 中没有直接的等价物。

  1. 如果对象很大(~大于 32-64 字节)和/或需要更改,则通过指针传递。
  2. 如果上述规则不适用,则按值传递。
  3. maps/channels/slices 是引用类型,它们包含内部指针,因此您不需要通过指针传递它们,除非您计划可能传递一个 nil 或想要附加(而不是修改已包含的元素)到切片。

例子:

func doMap(m *map[string]string) {
    if *m == nil {
        *m = map[string]string{}
    }
    .....
}

【讨论】:

  • map/channel 实际上是通过引用隐式传递的。
  • @NipunTalukdar 是的,这就是我这么说的原因,我想我应该说得更清楚。
  • 不应该是if *m == nil {吗?
  • @OneOfOne “结构是引用类型”?
  • @alexvasi 切片,哎呀
【解决方案2】:

对于字符串,您可以使用*string 作为参数,并且您似乎无法更改原始字符串:

package main

import (
    "fmt"
    )

func t1(s *string) {
    fmt.Println("Inside before: %s", *s)
    s2 := "tEsT1"
    s = &s2
    fmt.Println("Inside after 1: %s", *s)
}

func main() {
    var s = "test"
    fmt.Println("Ourside before: %v", s)
    t1(&s)
    fmt.Println("Ourside  after: %v", s)
}

打印:

Ourside before: %v test
Inside before: %s test
Inside after 1: %s tEsT1
Ourside  after: %v test

对于复杂的结构,通过 ref 并阻止编辑将更难或不可能。

如果我弄错了,请纠正我(我只是在学习 Go)。

【讨论】:

  • 字符串是通过引用传递的,但它们是不可变的,所以表现得就好像它们是通过值传递一样。
  • @NickCraig-Wood,这是否意味着如果我们通过像 t1(s string) 这样的值传递一个字符串,它不会复制到内存中,我们可以轻松地来回传递巨大的字符串?
猜你喜欢
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
  • 1970-01-01
  • 2021-12-10
相关资源
最近更新 更多