[[likely]]和[[unlikely]]是C++20引入的分支预测提示,用于指导编译器优化代码布局以提升CPU分支预测效率;前者适用于高频执行路径(如主流程、正常情况),后者适用于低频异常路径(如错误处理),需紧贴控制语句使用,效果依赖编译器和实际运行特征。
![c++中的[[likely]]和[[unlikely]]属性怎么用_c++ c++20分支预测优化【性能】](https://www.chuangxiangniao.com/wp-content/themes/justnews/themer/assets/images/lazy.png)
这两个属性是 C++20 引入的标准化分支预测提示,用于告诉编译器某条 if 分支(或 switch case)**大概率会执行**([[likely]])或**大概率不会执行**([[unlikely]])。它们本身不改变程序逻辑,只影响编译器生成的机器码布局(比如把高频路径放在更顺直的位置),从而提升 CPU 分支预测准确率和指令预取效率。
什么时候该加 [[likely]]
适用于明显偏向真值的条件判断,尤其是错误处理之外的主流程、循环中绝大多数迭代走的路径:
函数入口参数校验通过后继续执行(而非法参数是例外)容器非空时访问元素(if (!vec.empty()) { ... })内存分配成功后的使用(if (ptr) { ... },假设失败极少见)循环中每次迭代都执行的主体逻辑(可放在 for 或 while 后的语句块上)
示例:
if (x > 0) [[likely]] { // x 为正数是常见情况,编译器可能将这段代码紧接在条件跳转后 process_positive(x);}
什么时候该加 [[unlikely]]
专用于小概率事件,最典型的是错误处理、边界检查失败、异常路径:
立即学习“C++免费学习笔记(深入)”;
系统调用失败(如 open() 返回 -1)内存分配失败(new 抛异常或返回 nullptr)越界访问防护(if (i >= size) [[unlikely]] { throw ...; })调试断言未触发时的“正常”分支(但通常 assert 本身已含类似语义)
示例:
int* p = new(std::nothrow) int[1000000];if (!p) [[unlikely]] { // 内存耗尽非常罕见,编译器可能把这段挪到远离热路径的位置 log_error("OOM"); return false;}
写法细节和常见误区
属性必须紧贴在 if、switch、for、while、do 等语句之后(即作用于整个语句块),不能放在条件表达式内部或 else 上:
✅ 正确:if (cond) [[likely]] { ... } 或 if (cond) { ... } else [[unlikely]] { ... }❌ 错误:if ([[likely]] cond) { ... }(语法错误)❌ 错误:if (cond) { ... } [[unlikely]] else { ... }(位置错,应紧贴 else)⚠️ 注意:不支持直接修饰单个表达式或变量;也不能用于函数声明(那是 [[noreturn]] 的事)
实际效果与注意事项
是否生效取决于编译器实现和目标架构。GCC/Clang 在优化开启(-O2 及以上)时会响应这些提示,但不会强制重排代码——只是增加权重倾向。它不是银弹:
若预测与实际运行严重不符(比如标了 [[likely]] 的分支只在 1% 情况下执行),反而可能降低性能微基准测试容易受干扰,建议在真实负载 + perf / VTune 下验证收益优先保证算法和数据结构合理,再考虑这类底层提示C++20 之前可用编译器内置(如 GCC 的 __builtin_expect(!!(cond), 1)),但可读性差且非标准
基本上就这些。用对地方能白捡一点性能,用错反而添乱。
以上就是c++++中的[[likely]]和[[unlikely]]属性怎么用_c++ C++20分支预测优化【性能】的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1488258.html
微信扫一扫
支付宝扫一扫