C++20那些事之何时使用可能性属性?

news/2024/12/22 20:38:09/

C++20 引入了 [[likely]][[unlikely]] 这两个可能性属性,它们会给编译器优化提示,表示对应代码路径可能/不可能被执行。

乍一看,这似乎是一组很不错的属性,通过编译器优化,从而提高性能。但是事实并不是如此。

在C++ 标准草案中明确提到:Excessive usage of either of these attributes is liable to result in performance degradation.

即:过度使用任何一个属性都可能导致性能下降。

https://eel.is/c++draft/dcl.attr.likelihood#note-2

那么在什么情况下会比较有用,什么情况下又不需要呢?

本文谈谈自己的观点。

1.原则

使用时应该遵循以下原则:

  1. 谨慎使用:仅在你确定某个分支或路径在运行时极其可能或不可能时使用这些属性。

例如:下面这个判断一个value是不是大于0,如果输入的数据无法保证value很大概率/一定是大于0的,那么下面这个优化没有任何意义。

if (value > 0) [[likely]] {std::cout << "Value is positive: " << value << std::endl;
} else [[unlikely]] {std::cout << "Value is non-positive: " << value << std::endl;
}

例如:标准库中使用unlikely的示例。_Variant_storage结构体中的成员函数使用了这个属性,无效的概率非常低,所以可能使用unlikely去标记。

constexpr void
_M_reset()
{if (!_M_valid()) [[unlikely]]return;// do something
}
  1. 标记主导路径:只在主导执行路径上使用属性,而不是在所有可能路径上。

例如:下面一个if判断标记了两个等效的likely,那么这个意义不大。

if (value > 10) [[likely]] {// 主导路径:值大于 10std::cout << "Value is greater than 10: " << value << std::endl;
} else if (value > 5) [[likely]] {// 次主导路径:值大于 5 且小于等于 10std::cout << "Value is greater than 5 but less than or equal to 10: " << value << std::endl;
} else [[unlikely]] {// 较少出现的路径:值小于等于 5std::cout << "Value is 5 or less: " << value << std::endl;
}

2.示例

最后举一个比较常见的例子,那便是vector的at,我们知道它会判断是否超过vector的size,这种概率比较低,所以我们可以使用unlikely,例如:

int& at(std::vector<int>& vec, std::size_t i) {if (i >= vec.size()) [[unlikely]] {throw std::out_of_range("Out of bounds access");}return vec[i];
}

最后对这个做一个benchmark,得到一个对比图,可以看到使用unlikely可以提升一定的性能,但不太大,当让也与测试代码关系。

注:完整代码与测试步骤已发星球,感兴趣加入星球即可。

4d1419e5ac0ede58ea8970a9c8030baa.jpeg

一起探索更多C++项目/知识~

92c86b96a8eb918c9a689fd80076d966.jpeg

往期推荐:

向量数据库milvus源码剖析之开篇

热度更新,手把手实现工业级线程池

玩转cpp小项目星球3周年了!

95d7c4d653ac2e019af83cb2710cbba9.jpeg


http://www.ppmy.cn/news/1524365.html

相关文章

自动化立体仓库定义及使用范围

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》人俱乐部 这份文件是关于自动化立体仓库的定义、发展、组成、技术性能、应用领域、供货方式以及设计步骤的详细介绍。以下是核心内容的概要&#…

Java 入门指南:JVM(Java虚拟机)—— Java 内存运行时的数据区域

前言 对于 Java 程序员来说&#xff0c;在虚拟机自动内存管理机制下&#xff0c;不再需要像 C/C程序开发程序员这样为每一个 new 操作去写对应的 delete/free 操作&#xff0c;不容易出现内存泄漏和内存溢出问题。 由于程序员把内存控制权利交给 Java 虚拟机&#xff0c;一旦…

【数学建模】2024年国赛成绩公布时间预测

经过三天三夜的奋战&#xff0c;2024年数学建模国赛也宣告结束&#xff0c;相信这几天超高强度的比赛也让大家精疲力竭了&#xff0c;所以经过几天的调整&#xff0c;大家都恢复过来了吧。能够在高强度的压力下坚持这么久&#xff0c;大家都超级厉害的&#xff01; 当然完整提交…

解锁 macOS 剪贴板历史记录,高效复制、粘贴技巧

在Mac上&#xff0c;我们经常需要在不同文档之间复制和粘贴内容。然而&#xff0c;macOS自带的剪贴板只能保存最后一个复制项&#xff0c;这大大限制了我们的工作效率。幸运的是&#xff0c;一些第三方应用程序可以帮助我们查看和管理剪贴板的历史记录&#xff0c;从而提升我们…

排查 MyBatis XML 配置中的 IF 语句与传值名称不匹配的 Bug

文章目录 本文档只是为了留档方便以后工作运维&#xff0c;或者给同事分享文档内容比较简陋命令也不是特别全&#xff0c;不适合小白观看&#xff0c;如有不懂可以私信&#xff0c;上班期间都是在得 前言&#xff0c;在改一个bug得时候发现一个有意思得问题&#xff0c;就是myb…

变更AWS EC2 实例配置或实例类型

在本文中&#xff0c;九河云将带您了解如何更改由 Amazon Elastic Block Store (EBS) 支持的 Amazon Elastic Compute Cloud (EC2) 实例的类型。更改实例类型可以优化成本和性能&#xff0c;使其更符合您的应用程序需求。 准备工作 在开始之前&#xff0c;请确保您已完成以下…

java-redis-穿透

Redis 缓存穿透是指当请求的数据在缓存和数据库中都不存在时&#xff0c;用户每次请求都会直接查询数据库&#xff0c;导致缓存失效&#xff0c;无法发挥作用。这种情况下&#xff0c;用户发出的每个请求都绕过了缓存&#xff0c;直接打到了数据库&#xff0c;可能导致数据库压…

Mybatis-Plus笔记

本笔记基于【尚硅谷新版SSM框架全套视频教程&#xff0c;Spring6SpringBoot3最新SSM企业级开发】https://www.bilibili.com/video/BV1AP411s7D7?vd_sourcea91dafe0f846ad7bd19625e392cf76d8 总结 资料获取网址&#xff1a;https://www.wolai.com/v5Kuct5ZtPeVBk4NBUGBWF Myb…