golang切片里的坑

切片的传递为地址传递,但有以下问题:

1. 切片传递问题
切片本身传递给函数形参时是引用传递,但append后,切片长度变化时会被重新分配内存,而原来的切片还是指向原来地址,致使与初始状况传进来的地址不一样,要想对其值有改变操作,需使用指针类型操作。

// Findlinks1 prints the links in an HTML document read from standard input.
// leetcode 78. 子集
package main

import "fmt"

func helper(nums []int, res [][]int, tmp []int, level int) {
	if len(tmp) <= len(nums) {
		//长度一样的tmp用的是同一个地址,故可能会存在覆盖值得情况,
		// 长度不一样时重新开辟空间,将已有得元素复制进去
		//*res = append(*res, tmp) 如此处,最终长度为1的tmp会被最后3这个元素全部覆盖
		//以下相当于每次重新申请内存,使其指向的地址不一样,解决了最后地址一样的元素值被覆盖的状态状态
		var a []int
		a = append(a, tmp[:] ...)
		//res = append(res, a) 如果此处不是指针引用传递,在append后,res重新分配内存,与之前传进来的res地址不一样,最终res仍为空值
		res = append(res, a)
	}
	//fmt.Println(*res, "--->", tmp)
	for i := level; i < len(nums); i ++ {
		tmp = append(tmp, nums[i])
		helper(nums, res, tmp, i + 1)
		tmp = tmp[:len(tmp) - 1] //相当于删除tmp末位的最后一个元素
	}
}

func subsets(nums []int) [][]int {
	if len(nums) == 0 {
		return nil
	}
	var res [][]int
	var tmp []int
	helper(nums, res, tmp, 0)
	return res
}


func main()  {
	pre := []int{1, 2, 3}
	fmt.Println(subsets(pre))
}

// Findlinks1 prints the links in an HTML document read from standard input.
// leetcode 78. 子集
package main

import "fmt"

func helper(nums []int, res [][]int, tmp []int, level int) {
	if len(tmp) <= len(nums) {
		//长度一样的tmp用的是同一个地址,故可能会存在覆盖值得情况,
		// 长度不一样时重新开辟空间,将已有得元素复制进去
		//*res = append(*res, tmp) 如此处,最终长度为1的tmp会被最后3这个元素全部覆盖
		//以下相当于每次重新申请内存,使其指向的地址不一样,解决了最后地址一样的元素值被覆盖的状态状态
		var a []int
		a = append(a, tmp[:] ...)
		//res = append(res, a) 如果此处不是指针引用传递,在append后,res重新分配内存,与之前传进来的res地址不一样,最终res仍为空值
		res = append(res, a)
	}
	//fmt.Println(*res, "--->", tmp)
	for i := level; i < len(nums); i ++ {
		tmp = append(tmp, nums[i])
		helper(nums, res, tmp, i + 1)
		tmp = tmp[:len(tmp) - 1] //相当于删除tmp末位的最后一个元素
	}
}

func subsets(nums []int) [][]int {
	if len(nums) == 0 {
		return nil
	}
	var res [][]int
	var tmp []int
	helper(nums, res, tmp, 0)
	return res
}


func main()  {
	pre := []int{1, 2, 3}
	fmt.Println(subsets(pre))
}

输出结果:[]
修改代码后:

// Findlinks1 prints the links in an HTML document read from standard input.
// leetcode 78. 子集
package main

import "fmt"

func helper(nums []int, res *[][]int, tmp []int, level int) {
	if len(tmp) <= len(nums) {
		//长度一样的tmp用的是同一个地址,故可能会存在覆盖值得情况,
		// 长度不一样时重新开辟空间,将已有得元素复制进去
		//*res = append(*res, tmp) 如此处,最终长度为1的tmp会被最后3这个元素全部覆盖
		//以下相当于每次重新申请内存,使其指向的地址不一样,解决了最后地址一样的元素值被覆盖的状态状态
		var a []int
		a = append(a, tmp[:] ...)
		//res = append(res, a) 如果此处不是指针引用传递,在append后,res重新分配内存,与之前传进来的res地址不一样,最终res仍为空值
		*res = append(*res, a)
	}
	//fmt.Println(*res, "--->", tmp)
	for i := level; i < len(nums); i ++ {
		tmp = append(tmp, nums[i])
		helper(nums, res, tmp, i + 1)
		tmp = tmp[:len(tmp) - 1] //相当于删除tmp末位的最后一个元素
	}
}

func subsets(nums []int) [][]int {
	if len(nums) == 0 {
		return nil
	}
	var res [][]int
	var tmp []int
	helper(nums, &res, tmp, 0)
	return res
}


func main()  {
	pre := []int{1, 2, 3}
	fmt.Println(subsets(pre))
}

输出结果:[[] [1] [1 2] [1 2 3] [1 3] [2] [2 3] [3]]
2. 为二维切片(该值也是一个切片)append值的问题

// Findlinks1 prints the links in an HTML document read from standard input.
// leetcode 78. 子集
package main

import "fmt"

func helper(nums []int, res *[][]int, tmp []int, level int) {
	if len(tmp) <= len(nums) {
		//长度一样的tmp用的是同一个地址,故可能会存在覆盖值得情况,
		// 长度不一样时重新开辟空间,将已有得元素复制进去
		//*res = append(*res, tmp) 如此处,最终长度为1的tmp会被最后3这个元素全部覆盖
		//以下相当于每次重新申请内存,使其指向的地址不一样,解决了最后地址一样的元素值被覆盖的状态状态
		var a []int
		a = append(a, tmp[:] ...)
		//res = append(res, a) 如果此处不是指针引用传递,在append后,res重新分配内存,与之前传进来的res地址不一样,最终res仍为空值
		*res = append(*res, a)
	}
	//fmt.Println(*res, "--->", tmp)
	for i := level; i < len(nums); i ++ {
		tmp = append(tmp, nums[i])
		helper(nums, res, tmp, i + 1)
		tmp = tmp[:len(tmp) - 1] //相当于删除tmp末位的最后一个元素
	}
}

func subsets(nums []int) [][]int {
	if len(nums) == 0 {
		return nil
	}
	var res [][]int
	var tmp []int
	helper(nums, &res, tmp, 0)
	return res
}


func main()  {
	pre := []int{1, 2, 3}
	fmt.Println(subsets(pre))
}
//错误结果:[[] [3] [1 3] [1 2 3] [1 3] [3] [2 3] [3]], 可以看出,长度为1的切片都被3覆盖了,这由于它们的地址不一样
//正确输出:[[] [1] [1 2] [1 2 3] [1 3] [2] [2 3] [3]], 这是因为每次都为a分配内存,其地址都与之前的不一样,故最终的值没有被覆盖

转自:https://blog.csdn.net/vs974532452/article/details/101111671?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.add_param_isCf&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.add_param_isCf

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值