copy函数针对切片操作,底层内存空间的变化


在go语言中,copy函数针对切片进行复制操作,在底层中,内存空间可以互相重叠,也可以相互独立。


Go语言的内置函数 copy() 可以将一个数组切片复制到另一个数组切片中,如果加入的两个数组切片不一样大,就会按照其中较小的那个数组切片的元素个数进行复制。

copy() 函数的使用格式如下:

copy(destSlice, srcSlice []T) int

其中 srcSlice 为数据来源切片,destSlice 为复制的目标(也就是将 srcSlice 复制到 destSlice),目标切片必须分配过空间且足够承载复制的元素个数,并且来源和目标的类型必须一致,copy() 函数的返回值表示实际发生复制的元素个数,是len(dst)和len(src)中的最小值。


下面的代码展示了使用 copy() 函数将一个切片复制到另一个切片的过程:

slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{5, 4, 3}
copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中
copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置

虽然通过循环复制切片元素更直接,不过内置的 copy() 函数使用起来更加方便,copy() 函数的第一个参数是要复制的目标 slice,第二个参数是源 slice,两个 slice 可以共享同一个底层数组,甚至有重叠也没有问题。

首先讲一下数据空间相互重叠的情况:

	var arr = [5]int {1,2,3,4,5}
var slice1 []int = arr[:4]  // 1 2 3 4
var slice2 []int = arr[1:]  // 2 3 4 5
copy(slice1, slice2)  // 将slice2复制到slice1中
fmt.Println(arr)  // 2 3 4 5 5
fmt.Println(slice1)  // 2 3 4 5
fmt.Println(slice2)  // 3 4 5 5

由于切片是引用数据类型,所以在经过copy操作后,slice2会拷贝一份数据放进slice1引用的数据空间(即arr[:4])会变成[2, 3, 4, 5]。


ps:这里切片在内存中真正的布局其实并不是这样的,此处是为了看着方便特作简化操作。


此时数组arr中的值变成了[2, 3, 4, 5, 5],倘若我们对数组进行arr[1] = 100的操作,由于slice1和slice2引用的是同一个数据空间,所以slice1和slice2中的元素都会发生改变。


数据空间相互独立的情况:

	 var slice3 = []int{1, 2, 3, 4, 5}  // 1 2 3 4 5
 var slice4 = make([]int, 10)  // 默认值 0 0 0 0 0 0 0 0 0 0 0
copy(slice4, slice3)
slice3[0] = 100  // 只改变slice3的数据
fmt.Println(slice3)  // 100 2 3 4 5
fmt.Println(slice4)  // 1 2 3 4 5 0 0 0 0 0


slice3和slice4引用的是不同数据空间,copy函数只是将slice3中的数据拷贝一份放入slice4所引用的空间中,两者的内存空间是相互独立的。因此,当我们修改slice3中的数据时,slice4不会发生改变。


总结:1.copy函数是拷贝值,而不是修改切片的引用;2.切片是引用数据类型。

原文链接:https://blog.csdn.net/newbee_man/article/details/107039857

版权声明:
作者:超级管理员
链接: https://blog.apecloud.ltd/article/detail.html?id=98811b
来源:猿码云个人技术站
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
/static/admin/img/weixin.jpg/static/admin/img/zfb.jpg
<<上一篇>
暂无
下一篇>>