当切片的长度改变时,会分配一个新的内存空间吗?

huangapple go评论78阅读模式
英文:

Will a slice allocate a new memory space when len is changed?

问题

package main

import "fmt"

func main() {
	arr := make([]int, 3, 4)
	fmt.Println(fmt.Sprintf("切片操作前:长度:%d,容量:%d,地址:%p", len(arr), cap(arr), &arr))
	arr = arr[1:2]
	fmt.Println(fmt.Sprintf("切片操作后:长度:%d,容量:%d,地址:%p", len(arr), cap(arr), &arr))
}
切片操作前:长度:3,容量:4,地址:0xc0000a6020
切片操作后:长度:1,容量:3,地址:0xc0000a6020

切片操作前后的地址是相同的。

我的问题是,当切片的长度从3变为1时,切片会分配新的内存吗?

因为切片包含三个元素:Data uintptr、Len int、Cap int。
如果其中一个发生变化,我猜测会在内存中生成一个新的切片,这是正确的吗?

英文:
package main

import "fmt"

func main() {
	arr := make([]int,3,4)
	fmt.Println(fmt.Sprintf("before len:%d,cap:%d, address:%p",len(arr), cap(arr), &arr))
	arr = arr[1:2]
	fmt.Println(fmt.Sprintf("after len:%d,cap:%d, address:%p",len(arr), cap(arr), &arr))
}

before len:3,cap:4, address:0xc0000a6020
after len:1,cap:3, address:0xc0000a6020

the address before and after the slicing is the same.

My question is, will the slice allocate a new memory when its len is changed from 3 to 1.

Because slice have three-element, Data uintptr, Len int, Cap int
If one of them changes, My guess is that a new slice will be generated on the memory, is that true?

答案1

得分: 4

一个切片在增长到超过其容量时会重新分配其数据,但是头部不会移动。你可以通过&arr[0]来观察到这一点。如果你复制一个切片,你会得到一个新的、不同的头部,但是它们会共享数据,直到原始切片或复制切片的数据被重新分配。

package main

import "fmt"

func main() {
    arr := make([]int, 3, 4)
    arrCopy := arr
    fmt.Println(fmt.Sprintf("before   len:%d,cap:%d, address:%p, data:%p", len(arr), cap(arr), &arr, &arr[0]))
    arr = arr[1:2]
    fmt.Println(fmt.Sprintf("after    len:%d,cap:%d, address:%p, data:%p", len(arr), cap(arr), &arr, &arr[0]))
    arr = append(arr, arrCopy...)
    fmt.Println(fmt.Sprintf("appended len:%d,cap:%d, address:%p, data:%p", len(arr), cap(arr), &arr, &arr[0]))
    fmt.Println(fmt.Sprintf("arrCopy  len:%d,cap:%d, address:%p, data:%p", len(arrCopy), cap(arrCopy), &arrCopy, &arrCopy[0]))
}

(https://play.golang.org/p/Rtvt16DH_tj)

英文:

A slice will reallocate its Data if it grows larger than its capacity, but the header will not move. You would see this with &arr[0]. If you copy a slice, you get a new, different header, but they will share data, until the original or copy's data is reallocated.

package main

import "fmt"

func main() {
    arr := make([]int,3,4)
    arrCopy := arr
    fmt.Println(fmt.Sprintf("before   len:%d,cap:%d, address:%p, data:%p",len(arr), cap(arr), &arr, &arr[0]))
    arr = arr[1:2]
    fmt.Println(fmt.Sprintf("after    len:%d,cap:%d, address:%p, data:%p",len(arr), cap(arr), &arr, &arr[0]))
    arr = append(arr, arrCopy...)
    fmt.Println(fmt.Sprintf("appended len:%d,cap:%d, address:%p, data:%p",len(arr), cap(arr), &arr, &arr[0]))
    fmt.Println(fmt.Sprintf("arrCopy  len:%d,cap:%d, address:%p, data:%p",len(arrCopy), cap(arrCopy), &arrCopy, &arrCopy[0]))
}

(https://play.golang.org/p/Rtvt16DH_tj)

huangapple
  • 本文由 发表于 2021年8月9日 23:25:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/68714650.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定