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://apecloud.ltd/article/detail.html?id=128
来源:猿码云个人技术站
文章版权归作者所有,未经允许请勿转载。
共有0条评论