golang slice append 后 capacity 增长的算法

栏目: Go · 发布时间: 6年前

内容简介:函数定义:函数说明:内建函数append追加一个或多个elems到一个slice依赖的array的末尾,如果这个slice有足够的capacity,则reslice以容纳新增元素;如果capacity空间不够,则重新分配内存保存新的slice依赖的array,函数返回更新后的slice.(slice是引用,array保存真正的数据,slice切片理解:

一道题目:

golang slice append 后 capacity 增长的算法

append函数

函数定义: func append(slice []Type, elems ...Type) []Type

函数说明:内建函数append追加一个或多个elems到一个slice依赖的array的末尾,如果这个slice有足够的capacity,则reslice以容纳新增元素;如果capacity空间不够,则重新分配内存保存新的slice依赖的array,函数返回更新后的slice.(slice是引用,array保存真正的数据,slice切片理解: https://blog.haohtml.com/arch...

注意:append不会修改传参进来的slice(len和cap),只会在不够用的时候新分配一个array,并把之前的slice依赖的array数据拷贝过来;所以对同一个slice 重复 append,只要不超过cap,都是修改的同一个array,后面的会覆盖前面

capacity如何增长?

图片里提到"Capacity grows in a way not related to the size of appending data",那么,增长算法是什么样的呢?看源代码 src/runtime/slice.go:

newcap := old.cap
    doublecap := newcap + newcap
    if cap > doublecap {
        newcap = cap
    } else {
        if old.len < 1024 {
            newcap = doublecap
        } else {
            // Check 0 < newcap to detect overflow
            // and prevent an infinite loop.
            for 0 < newcap && newcap < cap {
                newcap += newcap / 4
            }
            // Set newcap to the requested cap when
            // the newcap calculation overflowed.
            if newcap <= 0 {
                newcap = cap
            }
        }
    }
  1. 先将旧的slice容量乘以2,如果乘以2后的容量仍小于新的slice容量,则取新的slice容量(append多个elems)
  2. 如果新slice小于等于旧slice容量的2倍,则取旧slice容量乘以2
  3. 如果旧的slice容量大于1024,则新slice容量取旧slice容量乘以1.25

代码后面还会对newcap进行roundup,比如在64位平台,newcap是奇数的话就会+1

回头看题

package main

import (
    "fmt"
)
func main(){
    a := []int{1,2}
    b := append(a,3)
    fmt.Printf("cap(a)=%v,cap(b)=%v\n",cap(a),cap(b))
    c := append(b,4)
    d := append(b,5)
    fmt.Printf("cap(a)=%v,cap(b)=%v\n",cap(a),cap(b))
    fmt.Println(a,b,c,d)
    fmt.Printf("%p,%p,%p,%p\n",a,b,c,d)
}

第一次append,超出了a的cap范围,分配一个新的newcap为oldcap*2的array,即4;a不变

第二次append,len(b)是3,cap(b)是4,没有超出b的cap范围,b所依赖的array在len(b)的位置追加4,c共用这个array;b不变

第三次append,由于b没有变化,b所依赖的array在len(b)的位置追加5,会覆盖上一步的4

所以:c[3]和d[3]引用的是同一块内存,都是5

另外,如果 d:= append(c,5) 则结果就是 c[3]=4,d[3]=4,d[4]=5因为这一步会新分配array,并将c的数据拷贝过来

总结

写得比较匆忙,如有纰漏,欢迎指正。


以上所述就是小编给大家介绍的《golang slice append 后 capacity 增长的算法》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

中国机器人

中国机器人

[中]王鸿鹏、[中]马娜 / 辽宁人民出版社 / 2017-1-1 / 48.00元

本书对中国机器人领域的发展历史做了引人入胜的介绍,中国机器人成长的过程也是中国经济由弱到强的历程。本书实际是选择了一个独特的视角来解读中国数十年的政治、经济、国家战略问题。中国的未来充满了多重可能性,本书对想了解中国当代与未来发展战略的读者是难得的读本,对智能制造这一当今世界*受关注的高科技领域在战略层面和科技伦理层面进行了深入地剖析和思考,其中提出的诸多前沿性观点是全球都将面对的问题,对中国科学......一起来看看 《中国机器人》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具