vector是连续内存加三指针结构,空vector访问v[0]或front()会崩溃;reserve只改capacity,resize才改size并初始化;erase后需更新迭代器;扩容使所有迭代器失效;clear不释放内存,缩容用swap或shrink_to_fit。

直接说结论:vector不是“能自动扩容的数组”这么简单——它是一块连续内存+三根指针(begin、end、capacity)的组合,用对了快得离谱,用错了轻则越界崩溃,重则迭代器悬空、数据错乱。
空 vector 用 v[0] 或 v.front() 就崩
这是线上最常出现的段错误来源之一。空 vector 的 begin() 和 end() 都是 nullptr,v[0] 直接解引用空指针;v.front() 同样不检查 size() > 0,行为未定义。
- 别写
v[0] = 1或int x = v.front(),除非你 100% 确保v.size() > 0 - 调试阶段一律用
v.at(0),越界抛std::out_of_range异常,有栈回溯可查 - 初始化就确定大小?优先用
v.resize(n)或带参构造vector<int>(n, 0)</int>,而不是先reserve(n)再瞎赋值
reserve 和 resize 完全是两回事
reserve(n) 只动 capacity(),不改变 size(),也不初始化任何元素;resize(n) 改 size(),必要时调用默认构造或填入值,但不一定动 capacity()。
-
v.reserve(100)后,v.size()还是 0,v[0]依然非法 -
v.resize(100)后,v.size() == 100,v[0]到v[99]全合法(值为T{}) - 批量插入前预分配?用
reserve;需要固定长度并访问下标?用resize
循环中删元素,erase 不返回新迭代器就完蛋
vector::erase(it) 会把 it 之后所有元素前移,原 it 所指位置被覆盖,该迭代器立即失效。继续 ++it 是未定义行为,VS 下可能断言失败,GCC 可能静默出错。
- 错:
for (auto it = v.begin(); it != v.end(); ++it) { if (...) v.erase(it); } - 对:
for (auto it = v.begin(); it != v.end(); ) { if (...) it = v.erase(it); else ++it; } - 更推荐:用
erase-remove惯用法,比如删偶数v.erase(remove_if(v.begin(), v.end(), [](int x){return x%2==0;}), v.end());
扩容时所有迭代器、指针、引用全失效
只要一次 push_back 触发了 reallocation(比如从容量 4 扩到 8),原来所有指向该 vector 元素的 iterator、pointer、reference 全部变成悬垂状态,哪怕只是读取也危险。
- 不要长期持有
&v[i]或&*it并在后续可能扩容的操作后还用它 - 函数传参要传
const vector<t>&</t>,别传vector<t>::iterator</t>后再调用push_back - 真需要稳定地址?考虑
deque或手动管理堆内存,vector的连续性代价就是这个
最易被忽略的一点:clear() 不释放内存,capacity() 不变;想真正缩容只能靠 vector<t>().swap(v)</t> 或 C++11 的 shrink_to_fit()(后者是请求,不保证成功)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











