用 std::vector 代替裸数组时应调用 reserve() 预分配内存,避免 push_back() 频繁扩容;若大小确定且不增删,直接用 vector(n) 构造并下标赋值更高效;注意 reserve() 不改变 size(),误用 resize() 可能引发默认构造开销。

用 std::vector 代替裸数组时,别忘了 reserve()
很多同学以为只要换成 std::vector 就自动高效了,其实频繁 push_back() 触发多次内存重分配,比裸数组还慢。尤其在已知元素数量的场景(比如读配置、解析日志),不预分配就是白送性能损耗。
- 先调
vec.reserve(n),再循环push_back(),避免隐式扩容(每次扩容通常是 1.5× 或 2×,伴随 memcpy) - 如果确定大小且不增删,直接用
std::vector<t>(n)</t>构造,然后通过下标赋值,比reserve() + push_back()更少函数调用开销 - 注意:
reserve()不改变size(),只影响capacity();误用resize()可能触发默认构造,对非 trivial 类型有额外成本
函数传参:const std::string& 还是 std::string_view?
C++17 起,std::string_view 是字符串只读访问的事实标准,但不是所有地方都适合一刀切替换。关键看调用方数据来源和生命周期。
- 接收字面量或临时
std::string时,std::string_view零拷贝、无内存分配,明显更快 - 如果函数内部可能存储该参数(比如塞进容器、缓存起来),不能用
string_view——它不拥有数据,源对象一销毁就悬空 - 对接 C API 或需要空终止符(
c_str())时,string_view无法直接满足,得转std::string,此时传const std::string&反而更稳
循环里别反复调用 vec.size() 或 map.size()
看似无害的写法:for (int i = 0; i ,在 debug 模式下可能没问题,但 release 下编译器未必能完全优化掉重复调用,尤其当循环体里有内联可能性低的函数或存在别名风险时。
免费的开源程序长期以来,为中国的网上交易提供免费开源的网上商店系统一直是我们的初衷和努力奋斗的目标,希望大家一起把MvMmall网上商店系统的免费开源进行到底。2高效的执行效率由资深的开发团队设计,从系统架构,数据库优化,配以通过W3C验证的面页模板,全面提升页面显示速度和提高程序负载能力。3灵活的模板系统MvMmall网店系统程序代码与网页界面分离,灵活的模板方案,完全自定义模板,官方提供免费模
- 把
size()提到循环外,存成局部const auto n = vec.size();,明确告诉编译器这是不变量 - 对
std::map/std::unordered_map更要小心:size()在某些实现里不是 O(1),虽然标准要求是常数时间,但老编译器或定制 allocator 下仍有意外 - 优先用范围 for(
for (const auto& x : vec)),既安全又让意图清晰,现代编译器对其优化非常成熟
std::move 不是银弹:什么时候真能提速?
滥用 std::move 可能导致移动语义失效,甚至引发静默性能回退。它只在“右值引用绑定”且类型支持移动操作时才真正起效。
立即学习“C++免费学习笔记(深入)”;
- 对
int、double、指针等 trivial 类型,std::move没意义,编译器自己会优化;强行加反而干扰判断 - 返回局部对象时,优先依赖 NRVO(命名返回值优化),而不是在 return 语句里写
std::move(local_obj)——后者会禁用 NRVO - 只有当你明确持有唯一所有权、且目标函数接受右值引用(如
void f(std::string&&))时,std::move才值得用;否则大概率只是多套了一层转换
真正卡顿的地方,往往藏在你以为“应该很快”的地方:比如一个被调用几千次的 getter 里偷偷 new 了小对象,或者某处 std::endl 强制刷缓冲拖慢 I/O。性能优化不是堆技巧,是拿 profiler 打开看,再一条条验证假设。









