深拷贝与浅拷贝

2021-06-27  本文已影响0人  牧神_c9dd

概念

golang开发时,我们会经常的把一个变量赋值给另一个变量,这个过程可能发生深拷贝也可能发生浅拷贝,二者有什么区别和联系呢?

1、深拷贝(Deep Copy)

深拷贝,拷贝的是数据本身,创造一个新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会影响原对象值。既然内存地址不同,释放内存地址时,可分别释放。

值类型的数据,默认全部都是深拷贝,Array、Int、String、Struct、Float,Bool。
package main

import (
    "fmt"
)

func main() {
    a := [3]int{1,2,3}
    b := a  //深拷贝
    b[0] = 4 //修改数组b的值,不影响数组a
    fmt.Println(a,b) //[1 2 3] [4 2 3]
}

2、浅拷贝(Shallow Copy)

浅拷贝,拷贝的是数据地址,只复制指向的对象的指针,此时新对象和老对象指向的内存地址是一样的,新对象值修改时老对象也会变化。释放内存地址时,同时释放内存地址。

引用类型的数据,默认全部都是浅拷贝,Slice,Map。
package main

import (
    "fmt"
)

func main() {
    a := []int{1,2,3}   //定义一个切片
    b := a  //浅拷贝
    b[0] = 4    //修改b的值,a的值也会跟着变
    fmt.Println(a,b)    //[4 2 3] [4 2 3]
    
    //map同样也是浅拷贝
    c := map[string]int {"柯南":98,"lufy":75,"naruto":86}
    d := c
    d["lufy"] = 88
    fmt.Println(c,d)    //map[lufy:88 naruto:86 柯南:98] map[lufy:88 naruto:86 柯南:98]
}

区别

深拷贝和浅拷贝的本质区别,在于是否真正获取(复制)对象实体,而不是仅仅引用。

扩容摆脱同根

从上述例子看出来,slice若不是深拷贝,或者重新生成新空间,无论通过参数传递还是使用 := 或者 [:]赋值都存在同根性。    

而扩容可以摆脱这种同根性。

Slice与Array最大的区别在于Slice不需要指定大小会自动扩容等一些特性,Slice在多次append元素时,若满足扩容策略,这时候内部就会重新申请一块内存空间,将原本的元素拷贝一份到新的内存空间上。此时其与原本的数组就没有任何关联关系了,再进行修改值也不会变动到原始数组。
package main

import (
    "fmt"
)

func main() {
    a := []int{1,2,3}   //定义一个切片
    b := a[0:1]     
    for i:=0;i<=6;i++{
        b = append(b,i) //容量未满时是浅拷贝,一旦扩容就是深拷贝了
    }
    b[0] = 10   //验证
    fmt.Println(a,b)    //[1 0 1] [10 0 1 2 3 4 5 6]
    
}
上一篇下一篇

猜你喜欢

热点阅读