c++oding="utf-8" ?>
应优先使用 empty() 判断 vector 是否为空,因其语义清晰、安全零开销且可移植;size() == 0 虽性能相当,但存在类型警告风险与潜在维护误导。

判断 vector 是否为空,直接用 empty() 就行
别纠结 size() == 0,empty() 是标准、安全、零开销的写法。C++ 标准要求所有标准容器的 empty() 必须是常数时间,且不引发任何副作用——它不访问元素、不触发分配器操作、不检查内部缓冲区有效性。
而 size() 虽然对 std::vector 也是 O(1),但它返回的是一个无符号整型(size_type),拿它和 0 比较时,编译器可能插入隐式类型转换或警告(尤其开启 -Wsign-compare 时)。更关键的是:某些自定义分配器或调试模式下的 vector 实现,size() 可能有微小额外开销(比如校验计数一致性),empty() 则完全规避这些。
empty() 和 size() == 0 在汇编层几乎没区别,但语义差很多
现代编译器(GCC/Clang/MSVC)在优化开启(-O2)下,对 v.empty() 和 v.size() == 0 生成的汇编指令通常完全一致:都是读取内部指针(begin_)和容量/大小字段,做一次指针相等比较或整数比较。性能上真没差别。
但语义上:empty() 明确表达“我只关心逻辑空状态”,而 size() == 0 隐含了“我要先算出大小再比”,这在代码审查、协作或后续维护中容易误导。尤其当容器类型从 vector 换成 list 或 forward_list(size() 可能非 O(1))时,empty() 仍保持高效且可移植。
别在循环里反复调用 empty() 或 size() —— 这不是效率问题,是逻辑陷阱
常见错误写法:
while (!vec.empty()) {
auto x = vec.back();
vec.pop_back();
// ... 处理 x
}
这段代码本身没问题,但如果误写成:
vec.size()
- 判空用
empty(),简洁又意图清晰 - 遍历用范围
for或迭代器,避免手动索引 - 真要索引遍历且需长度,先缓存
const auto n = vec.size();再进循环
调试构建下 empty() 依然可靠,但注意迭代器失效场景
某些 STL 调试版本(如 libstdc++ 的 _GLIBCXX_DEBUG 或 MSVC 的 _ITERATOR_DEBUG_LEVEL)会对 empty() 做额外检查(比如验证内部指针是否合法),但这不影响其正确性,也不会导致崩溃——它只是让断言失败更早暴露问题。
真正要注意的是:调用 empty() 本身不会使迭代器失效,但如果你在判断后立刻调用 clear() 或 resize(0),那之前保存的迭代器、引用、指针全失效。这不是 empty() 的锅,但新手容易把“判空”和“清空”混为一谈。
复杂点在于:有些团队封装了带日志或监控的 vector 子类,重载了 size() 但忘了同步更新 empty(),这时候必须确认重载逻辑——标准实践是让 empty() 直接复用 size() 判断,而不是另起炉灶。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











