Go标准库优先队列Pop方法切片截断赋值原理咨询
问题解答
*pq = old[0 : n-1] 这行代码不会创建新的底层数组,也不会发生元素拷贝,仅会复用原切片的底层数组,调整切片的长度元信息为n-1,完全没有你担心的额外拷贝开销,非常适合大数量级优先队列的场景。
原理说明
Go语言的切片本质是一个包含3个字段的轻量结构体:
- 指向底层数组的指针
- 切片当前长度(len)
- 切片最大容量(cap)
你提到的代码逻辑里,所有切片操作都是复用同一个底层数组:
old := *pq仅拷贝了切片的三个元字段,和原切片共享底层数组,没有拷贝任何元素old[0 : n-1]是切片截取操作,只要没有超出原切片的容量范围,生成的新切片依然指向原底层数组,仅把长度字段修改为n-1,容量保持和原切片一致,全程没有元素拷贝- 赋值给
*pq的过程也仅拷贝了新切片的三个元字段,没有额外开销
额外补充说明
- 代码里的
old[n-1] = nil是必要的安全操作:因为你的PriorityQueue是指针切片,如果不把弹出位置的指针置空,原底层数组会一直持有该元素的引用,导致该元素无法被GC回收,造成隐性内存泄漏,这个操作没有额外性能开销。 - 只有在Push元素触发切片扩容的时候,才会发生底层数组的拷贝,Pop操作全程不会触发扩容,性能稳定。
内容的提问来源于stack exchange,提问作者Dean
相关产品推荐
相关产品推荐

