首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在go中将指针传递到片时的意外行为

在go中将指针传递到片时的意外行为
EN

Stack Overflow用户
提问于 2018-05-21 15:04:08
回答 2查看 113关注 0票数 1

下面的go程序应该生成整数片的所有排列:

代码语言:javascript
复制
package main
import "fmt"

func permute(nums []int) [][]int {
    var res [][]int
    var s []int
    permuteHlp(&res, nums, 0, s)
    return res
}

func permuteHlp(res *[][]int, nums []int, i int, s []int) {
    if i == len(nums) {
        *res = append(*res, s)
        return
    }

    for j := i; j < len(nums); j++ {
        s = append(s, nums[j])
        nums[i], nums[j] = nums[j], nums[i]
        permuteHlp(res, nums, i+1, s)
        s = s[:len(s)-1]
        nums[i], nums[j] = nums[j], nums[i]
    }
}

func main() {
    x := []int{1,2,3,4}
    y := permute(x)

    fmt.Println(y)
}

输出是意外的。

代码语言:javascript
复制
[[1 2 4 3] [1 2 4 3] [1 3 4 2] [1 3 4 2] [1 4 2 3] [1 4 2 3] [2 1 4 3] [2 1 4 3] [2 3 4 1] [2 3 4 1] [2 4 1 3] [2 4 1 3] [3 2 4 1] [3 2 4 1] [3 1 4 2] [3 1 4 2] [3 4 2 1] [3 4 2 1] [4 2 1 3] [4 2 1 3] [4 3 1 2] [4 3 1 2] [4 1 2 3] [4 1 2 3]]

我不明白这是怎么回事。我很感谢你的帮助。谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-05-21 15:21:28

不需要指向切片的指针,因为切片本身就是指针。“片是对数组的连续段的引用。”,参考文献

您所看到的奇怪行为是因为您正在使用append,当一个片增长到超出其容量时,它需要创建一个具有更大容量的新片,并复制原始片的所有内容(这就是append在幕后所做的),因此新的切片不再指向原始的基础数组。

与修改传入参数不同,我建议将切片作为函数的返回值返回。

代码语言:javascript
复制
func permute(nums []int) [][]int {
   res := permuteHlp(nums, 0, new([]int))
   return res
}

我建议您阅读golang.org中关于片内件的博客文章,这里

编辑:

我添加了一个重构,采用了这个答案的算法。

代码语言:javascript
复制
package main

import (
    "fmt"  
)

func permutations(arr []int)[][]int{
    var helper func([]int, int)
    res := [][]int{}

    helper = func(arr []int, n int){
        if n == 1{
            tmp := make([]int, len(arr))
            copy(tmp, arr)
            res = append(res, tmp)
        } else {
            for i := 0; i < n; i++{
                helper(arr, n - 1)
                if n % 2 == 1{
                    tmp := arr[i]
                    arr[i] = arr[n - 1]
                    arr[n - 1] = tmp
                } else {
                    tmp := arr[0]
                    arr[0] = arr[n - 1]
                    arr[n - 1] = tmp
                }
            }
        }
    }
    helper(arr, len(arr))
    return res
}

func main() {
    x := []int{1,2,3,4}
    d := permutations(x)
    fmt.Print(d)
}

通常,您不希望有指向片的指针,相反,从函数返回一个新的指针,这是另一件需要注释的事情,如果可能的话,尽量不要使用递归,因为golang没有尾调用优化,它的循环执行得非常出色。希望能帮上忙!

票数 0
EN

Stack Overflow用户

发布于 2018-05-21 15:08:25

你在传递指向同一片的指针。最后,您将得到一堆指向结果中同一片的指针,因此,所有的值当然都是相同的--它是一次又一次打印的同一个片段。

还值得注意的是,指向片的指针很少是您想要的,因为切片已经包含了指向基础数组的指针。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50451609

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档