C++八股文:vector扩容机制选择
·
C++八股文:vector扩容机制选择
一句话时间
“
vector在容量用尽时会分配更大连续区并把旧元素搬到新区(移动或拷贝),这是摊销常数时间保证的来源;增长因子实现定义,常用 2× 或 1.5×,扩容会使所有指针/引用/迭代器失效,使用reserve和emplace_back可避免或减小开销。
关键细节(逐条要点)
- 触发条件:当调用
push_back/emplace_back/insert并且size() == capacity()时触发重新分配。reserve(n)` 可以提前设置容量,避免扩容。 - 增长策略是实现定义的:标准不规定确切增长因子;常见实现:libstdc++ 常见以接近 2×(倍增)增长,libc++ / MSVC 常见以约 1.5× 的增长(实现细节随版本变化)。
- 搬迁(move vs copy):重新分配时元素会被 搬到 新内存:优先使用 移动构造(move),如果没有 noexcept 的移动构造,会退回到拷贝构造(库通常使用
std::move_if_noexcept策略以保证异常安全)。 - 异常安全:为了避免在搬迁中抛出导致状态损坏,标准库倾向于在可能抛出的移动构造无法保证安全时使用拷贝;如果元素既不可拷贝又移动会抛,扩容会导致异常传播(操作失败),但实现会保证容器不会泄露资源且处于合法状态(具体保证级别依实现)。
- 代价:
push_back是 摊销常数时间(amortized O(1)),但扩容一次需要 O(n) 来搬移所有元素(n=旧 size)。 - 后果:扩容 使所有指针/引用/迭代器失效(到元素),除了某些实现对
std::vector<bool>等特化以外。 - 初始容量:默认空
vector的capacity()常为 0;第一次扩容常变为 1 或实现选择的最小容量。 shrink_to_fit():只是“请求”释放多余容量,非强制(实现可忽略);swap一个空的临时向量是更强的收缩方式。resize(n):改变size(会构造/析构元素),如果n大于capacity会触发扩容。reserve(n)只改变capacity不改变size。
面试常问要点(简洁可背)
- 什么时候扩容? 当
size()==capacity再插入元素。可用reserve()预分配避免扩容。 - 复杂度? 平均/摊销 O(1),单次扩容 O(n)。
- 元素如何搬移? 使用移动构造(若可用且 noexcept),否则拷贝构造(
move_if_noexcept)。 - 扩容对迭代器/指针影响? 全部失效(指向元素的指针/引用/迭代器都可能失效)。
- 如何避免扩容开销? 事先
reserve(预计大小);尽量用emplace_back就地构造。 - 增长因子是多少? 实现定义,常见为 2× 或 ~1.5×(不要死记,面试说“实现定义,常见2×或1.5×”即可)。
- 异常安全怎么做的? 库用
move_if_noexcept策略,优先选择不会抛的操作以提供更强的保证;若无法,扩容可能抛出。
更多推荐



所有评论(0)