应使用const引用传递避免临时对象构造,预分配vector内存减少重分配,优先利用移动语义替代拷贝,循环外提取重复计算,字符串比较用string_view或const char*。

用 const 引用代替值传递参数
循环中频繁构造临时对象,常源于函数调用时把对象按值传入。比如 std::vector<:string></:string> 遍历时写成 for (auto s : vec),每次迭代都复制一个 std::string ——尤其字符串内容长时开销明显。
改用 const auto& 直接绑定原对象,避免拷贝构造:
for (const auto& s : vec) { // 不触发 string 拷贝
process(s);
}
- 若需修改副本,再显式写
auto s = item,明确意图 - 对 POD 类型(如
int、double),引用反而可能略慢,但编译器通常会优化掉;不必为这点微小差异牺牲可读性 - 注意:不能对右值(如临时对象)取非常量引用,
const auto&可绑定右值,但auto&不行
reserve() 预分配 vector 内存
循环中反复 push_back() 容易触发多次内存重分配 + 元素逐个拷贝(或移动),尤其是存储非 trivial 类型时。这不是“每次迭代复制对象”,而是“因容量不足被迫批量复制”。
提前知道大致数量?直接 reserve():
std::vector<heavyobject> results;
results.reserve(expected_count); // 一次性分配足够内存
for (const auto& x : input) {
results.push_back(compute(x)); // 不再触发 realloc + copy
}</heavyobject>
-
reserve()只影响 capacity,不改变 size,也不调用元素构造函数 - 如果完全不确定大小,至少用
reserve(16)或类似小值兜底,减少早期频繁扩容 - 注意:
resize()会构造默认对象,不是替代方案
移动语义替代拷贝(C++11 起)
当必须生成新对象(如工厂函数返回、容器插入),优先让类型支持移动构造/赋值。否则即使写了 std::move(),也会退化为拷贝。
检查类是否满足“可移动”条件:
- 没有用户定义的拷贝构造/拷贝赋值(或它们是 defaulted)
- 有 noexcept 的移动构造/移动赋值(推荐显式加
noexcept) - 成员变量本身也支持移动(如
std::string、std::vector默认支持)
循环中使用示例:
std::vector<bigbuffer> buffers;
for (int i = 0; i <p>若你控制不了 <code>create_buffer</code> 的返回类型,至少确保接收端不强制拷贝:<code>push_back(std::move(temp))</code> 是安全的,但别对 const 对象或函数返回值重复 move —— 编译器已处理好。</p>
<h3>避免在循环条件里重复计算或隐式转换</h3>
<p>看似不相关,但常导致意外拷贝:比如 <code>for (size_t i = 0; i ,每次迭代都调用 <code>get_data()</code>(返回 <code>std::vector</code> 副本)再取 <code>size()</code>。</code></p>
<p>更糟的是带隐式转换的比较:</p>
<pre class="brush:php;toolbar:false;">// 错误:每次循环都构造 std::string 临时对象
for (const auto& item : items) {
if (item.name == "target") { ... } // item.name 是 const char*
}
- 把
obj.get_data().size()提到循环外,或改用范围 for - 字符串字面量比较尽量用
std::string_view(C++17)或直接比const char*,避免构造std::string - 自定义类型重载
operator==时,参数用const T&,别用值传参
真正关键的不是“少写几行”,而是每次迭代前,问一句:这个表达式有没有悄悄 new 一个对象出来?
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











