题目序号:(225、2462、4794、6617)
频次:4
题目来源:映客,腾讯,北京合链
答案1:(小小)+
深拷贝,浅拷贝概念
- 深拷贝(Deep Copy):
拷贝的是数据本身,创造一个样的新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会影响原对象值。既然内存地址不同,释放内存地址时,可分别释放。
- 浅拷贝(Shallow Copy):
拷贝的是数据地址,只复制指向的对象的指针,此时新对象和老对象指向的内存地址是一样的,新对象值修改时老对象也会变化。释放内存地址时,同时释放内存地址。参考来源
在go语言中值类型赋值都是深拷贝,引用类型一般都是浅拷贝:
- 值类型的数据,默认全部都是深拷贝:Array、Int、String、Struct、Float,Bool
- 引用类型的数据,默认全部都是浅拷贝:Slice,Map
对于引用类型,想实现深拷贝,不能直接 := ,而是要先开辟地址空间(new) ,再进行赋值。
怎么进行(切片的)深拷贝?
可以使用 copy() 函数来进行深拷贝,copy 不会进行扩容,当要复制的 slice 比原 slice 要大的时候,只会移除多余的。
func main() {
slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{6, 7, 8}
copy(slice2, slice1) // 复制slice1的前3个元素到slice2中
fmt.Println(slice1, slice2)
copy(slice1, slice2) // 复制slice2的3个元素到slice1的前3个位置
fmt.Println(slice1, slice2)
}
使用 append() 函数来进行深拷贝,append 会进行扩容(这里涉及到的就是 Slice 的扩容机制 )。
func main() {
a := []int{1, 2, 3}
b := make([]int, 0)
b = append(b, a[:]...)
fmt.Println(a, b)
a[1] = 1000
fmt.Println(a, b)
fmt.Printf("%p,%p", a, b)
}
Go 中切片扩容的策略:
- 首先判断,如果新申请容量大于 2 倍的旧容量,最终容量就是新申请的容 量
- 否则判断,如果旧切片的长度小于 1024,则最终容量就是旧容量的两倍
- 否则判断,如果旧切片长度大于等于 1024,则最终容量从旧容量开始循环 增加原来的 1/4, 直到最终容量大于等于新申请的容量
- 如果最终容量计算值溢出,则最终容量就是新申请容量
注意:如果 slice 在 append() 过程中没有发生扩容,那么修改就在原来的内存中,如果发生了扩容,就修改在新的内存中。
本文来自投稿,不代表本站立场,如若转载,请注明出处: