指向指针的指针(例如** int)有什么用例? [英] What use case does pointers to pointer (eg **int) have?

查看:130
本文介绍了指向指针的指针(例如** int)有什么用例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是指向指针的指针

package main

import "fmt"

func main() {
    var num int

    fmt.Println(&num) //  0x...0
    makePointer(&num)
}

func makePointer(firstPointer *int) {
    fmt.Println(firstPointer)  //  0x...0
    fmt.Println(&firstPointer) //  0x...1

    makePointerToAPointer(&firstPointer)
}

func makePointerToAPointer(secondPointer **int) {
    fmt.Println(secondPointer)  //  0x...1
    fmt.Println(&secondPointer) //  0x...2

}

您何时会真正使用它?您可以适当地提出一些可以更轻松地执行其他操作的方法,但这不是我要的.我真的很想知道您将在生产中使用它吗?

When would you actually use this? You can properly come up with something where it would be easier to do something else, but that is not what I asking about. I really want to know where in production you would use this?

推荐答案

将指针传递给某物的目的是是否需要 修改指针值. (我们也使用指针来避免在传递时复制大型数据结构,但这只是为了优化.)

The goal to pass a pointer to something is if there is need to modify the pointed value. (We also use pointers to avoid copying large data structures when passing, but that is just for optimization.)

如本例所示:

func main() {
    var i int
    fmt.Println(i)
    inc(&i)
    fmt.Println(i)
}

func inc(i *int) {
    *i++
}

期望的输出结果(在游乐场上尝试):

Output is the expected (try it on the Go Playground):

0
1

如果inc()的参数仅接收到int,则它只能修改副本,而不能修改原始值,因此调用者将不会观察到更改后的值.

If parameter of inc() would receive an int only, it could only modify the copy and not the original value, and so the caller would not observe the changed value.

相同的东西也带有指向某物的指针.如果需要修改指向的值,则使用指向某个对象的指针,即指向的指针.像本例一样:

Same goes with pointer to pointer to something. We use pointer to pointer to something, if we need to modify the pointed value, that is the pointed pointer. Like in this example:

func main() {
    var i *int
    fmt.Println(i)
    alloc(&i, 1)
    fmt.Println(i, *i)

    setToNil(&i)
    fmt.Println(i)
}

func alloc(i **int, initial int) {
    *i = new(int)
    **i = initial
}

func setToNil(i **int) {
    *i = nil
}

输出(在游乐场上尝试):

<nil>
0x1040a130 1
<nil>

之所以没有真正使用指向指针的原因,是因为可以通过返回值并将其分配给调用方来代替修改指向的值:

The reason why pointer to pointer is not really used is because modifying a pointed value can be substituted by returning the value, and assigning it at the caller:

func main() {
    var i *int
    fmt.Println(i)
    i = alloc(1)
    fmt.Println(i, *i)

    i = setToNil()
    fmt.Println(i)
}

func alloc(initial int) *int {
    i := new(int)
    *i = initial
    return i
}

func setToNil() *int {
    return nil // Nothing to do here, assignment happens at the caller!
}

输出相同(地址可能不同)(在进入游乐场上尝试):

Output is the same (address might be different) (try it on the Go Playground):

<nil>
0x1040a130 1
<nil>

此变体更易于阅读和维护,因此,这显然是必须修改指针值的函数的广泛青睐的选择.

This variant is easier to read and maintain, so this is clearly the favored and wide-spread alternative to functions having to modify a pointer value.

在函数和方法只能有1个返回值的语言中,如果函数还希望返回除指针之外的其他值,例如,通常需要附加的工作".将创建一个包装器以容纳多个返回值.但是由于Go支持多个返回值,因此指针指针的需求基本上降为零,因为可以用返回设置为指向指针的指针代替它.并且不需要额外的工作,也不会使代码的可读性降低.

In languages where functions and methods can only have 1 return value, it usually requires additional "work" if the function also wants to return other values besides the pointer, e.g. a wrapper is to be created to accommodate the multiple return values. But since Go supports multiple return values, need for pointer to pointer basically drops to zero as it can be substituted with returning the pointer that would be set to the pointed pointer; and it does not require additional work and does not make code less readable.

这与内置 append() 函数非常相似:它会追加值切片.并且由于切片值发生变化(其长度增加,如果需要分配新的后备数组,其中的指针也可能会更改),因此append()返回您需要分配的新切片值(如果要保留新片).

This is a very similar case to the builtin append() function: it appends values to a slice. And since the slice value changes (its length increases, also the pointer in it may also change if a new backing array needs to be allocated), append() returns the new slice value which you need to assign (if you want to keep the new slice).

请参阅以下相关问题,其中提出了一个指向指针的指针(但也可以返回/也可以使用指针):

See this related question where a pointer to pointer is proposed (but also returning a pointer is also viable / preferred): Golang: Can the pointer in a struct pointer method be reassigned to another instance?

这篇关于指向指针的指针(例如** int)有什么用例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆