Const reference in C++ and equivalent in Golang

huangapple go评论79阅读模式
英文:

Const reference in C++ and equivalent in Golang

问题

在C++中,当你关心性能并且不需要修改对象时,通常会使用常量引用来传递对象。

void func(const std::string& str)

在这种情况下,字符串不会被复制,并且无法在函数中修改。

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

  • 按值传递,这样你就无法修改对象(实际上你可以修改,但没有意义),但会占用大量内存。
  • 按指针传递,从内存的角度来看是不错的选择,但你可以修改对象。

那么,最佳的方法是什么?即使你不想修改对象,是否总是通过指针传递对象会更快?或者是否存在一些编译器优化,即使你按值传递,有时也会按引用传递?

英文:

I came to go from the C++ world and in C++ usually when you care about performance and you don't need you object to be changed, you pass it using constant reference

void func(const std::string& str)

In this case, the string is NOT COPIED and cannot be modified in the function.

I know, that in Go there are two ways to pass object:

  • By value, and then you cannot modify (or actually you can but it makes no sense) it, but it very memory consuming
  • By pointer, this is good from the terms of memory, but you can modify object.

So, what is best approach? Always pass object by pointer even if you don't want to modify it because it is faster? Or there are some compiler optimizations and even if you send it by value sometimes it is sent as reference?

答案1

得分: 7

在Go语言中没有直接的等价方式。

  1. 如果对象很大(大于32-64字节)和/或需要修改,则通过指针传递。
  2. 如果不符合上述规则,则通过值传递。
  3. 映射/通道/切片是引用类型,它们包含内部指针,因此除非你打算可能传递一个nil或者想要向切片追加(而不是修改已包含的元素),否则不需要通过指针传递它们。

示例:

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

There's no direct equivalent in Go.

  1. Pass by pointer if the object is big (~bigger than 32-64bytes) and/or requires changing.
  2. Pass by value if the above rule doesn't apply.
  3. maps/channels/slices are reference-types, they contain inner pointers, so you don't need to pass them by pointer unless you plan on possibly passing a nil or want to append (not modify already contained elements) to a slice.

Example:

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

答案2

得分: -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

对于复杂的结构体,要通过引用传递并防止修改可能会更困难或不可能。

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

英文:

For strings you can use *string as parameter and it seems you can not change the original 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)
}

Prints:

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

For complex structs it would be harder or impossible to pass be ref & prevent editing.

Please correct me if I got it wrong (i'm just learning Go).

huangapple
  • 本文由 发表于 2016年4月11日 22:40:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/36551835.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定