为何C++中vector的容量以1.5倍的因子增长?
你猜的没错,这确实和均摊时间复杂度直接相关,同时还要平衡内存利用率,1.5倍是多方权衡后的结果:
保证均摊O(1)的push_back性能
vector是连续内存容器,扩容时需要分配新内存、拷贝旧元素、释放旧内存。如果每次扩容只加固定大小(比如每次多10个位置),最坏情况下push_back的时间复杂度会是O(n)——比如连续插入n个元素时,扩容次数是O(n/k)(k为固定增量),总拷贝操作数会达到O(n²/k),均摊到每个元素就是O(n)。
而用倍数扩容(比如1.5倍)时,每个元素被拷贝的次数是有限的:假设初始容量为c,每次扩容到1.5倍,一个元素最多会在容量从c→1.5c→2.25c→…的过程中被拷贝,总共被拷贝log_{1.5}(总元素数/c)次,总拷贝操作数是O(n),均摊到每个push_back就是O(1),这是vector能高效支持尾插的核心原因。平衡内存浪费与扩容频率
如果用2倍增长,扩容后剩余的空闲空间等于原来的容量,当后续插入元素不多时,这些空闲空间会长期闲置,内存浪费严重。1.5倍的增长幅度更温和,既能大幅减少扩容次数(远少于固定增量的情况),又不会造成过多的内存冗余。适配内存分配器的特性
多数内存分配器会按对齐的块大小(比如8字节、16字节或更大的对齐单位)分配内存,1.5倍增长后的容量更容易匹配这些标准块大小,减少内存碎片。同时1.5倍是整数倍与分数倍的折中,计算起来也简单(很多实现里直接用原容量*3/2的整数运算,避免浮点数操作)。历史实现的主流选择
不同标准库实现有不同的选择:比如GCC的libstdc++用1.5倍,MSVC用2倍,但1.5倍因为在时间效率和空间利用率之间的平衡更优,成为了广泛采用的方案。
内容的提问来源于stack exchange,提问作者malove

