从C++11升级至C++17,它们让嵌入式系统更好了!

李肖遥 2023-06-13 11:31
    关注、星标公众号,直达精彩内容



2011 年 8 月,ISO 委员会发布了 C++11,2017 年 12 月又发布了 C++17 标准,每次编程语言新版本的迭代,会令不少团队也开始着手升级开发环境,例如本文作者。那么从 C++11 升级到 C++17,究竟有哪些特别的变化值得关注?

原文链接:https://interrupt.memfault.com/blog/cpp-17-for-embedded

未经允许,禁止转载!

作者 | Çağlayan Dökme
译者 | 弯月   责编 | 郑丽媛
出品 | CSDN(ID:CSDNnews)

最近,我们团队正在升级开发环境,尝试使用许多工具和编程语言的新版本。在这个过程中,比较困难的一项工作是将我们的嵌入式应用程序的代码库从 C++11 升级到 C++17。

在本文中,我将展示在嵌入式世界中非常有用的一些 C++17 的特性(注意:从 C++11 迁移到 C++17 也涵盖了 C++14,因此我也会提到 C++14 的一些特性)

看完整的 C++17 性列表,可前往:https://github.com/AnthonyCalandra/modern-cpp-features#c17-language-features。


C++14 的主要变化

当初,我们从 C++03 迁移到了 C++11,与之相比,从 C++11 升级到 C++14 时看到的升级比较小。因此,可以在嵌入式系统中使用的 C++14 特有功能实际上并不多。

二进制字面量

如果你经常需要执行按位运算或修改寄存器,那么一定很喜欢这些字面量。一些编译器具有支持此类字面量的扩展,这些字面量在实际的标准中也有一席之地。

uint8_t a = 0b110; // == 6uint8_t b = 0b1111'1111; // == 255

constexpr**

在 C++14 中,可以在 constexpr 函数中使用的语法得到了扩展。constexpr 特别适用于嵌入式开发,因为它可以在编译时进行计算并将一些代码简化为常量。请注意,只有当表达式的所有需求都可以在编译期间确定时,才能在编译时计算表达式。

constexpr int factorial(int n) {if (n <= 1) {return 1;} else {return n * factorial(n - 1);}}factorial(5); // == 120 (Calculated at compile time)


C++ 17 的世界

与 C++14 相比,C++17 标准有了很大的变化,但无需担心,你仍然可以使用已有的功能。除了已有功能之外,你还将拥有更强大的 C++17 语法和库。

(1)属性

首先,我们来介绍三个新属性:[[fallthrough]]、[[nodiscard]] 和 [[maybe_unused]]。因为这些属性只在编译时考虑,所以你根本不需要担心它们的效率。它们的存在就是为了提升代码开发。

[[fallthrough]]

你可以利用这个属性将两个相邻的 case 分支的主体合并到一个 switch 中,而不会收到来自编译器的任何警告。你可以通过这个属性告诉编译器前一个case主体结束是有意为之。

switch (n) {case 1: [[fallthrough]]// ...// no `break;`case 2:// ...break;}

[[nodiscard]]

你是不是也经常忘记检查函数的返回值?有了这个属性,丢弃返回值就会收到编译器的警告。

[[nodiscard]] bool do_something() {return is_success; // true for success, false for failure}do_something(); /* warning: ignoring the return value of function declared with attribute 'nodiscard' */

[maybe_unused]]

为了避免收到警告,必须将未使用的变量转换为 void,你是不是也感到不耐烦?试试看这个属性,你就可以摆脱那些烦人的警告。

void my_callback(std::string msg, [[maybe_unused]] bool error) {// Don't care if `msg` is an error message, just log it.log(msg);}

(2)编译时的力量

编译时的检查是我最喜欢 C++ 的地方。在 C++17 中,这种能力通过一些新特性得到进一步增强。想一想许多嵌入式系统中繁琐的调试过程,如今甚至不需要部署代码就可以检查结果,是不是觉得是个特大好消息?传输可执行文件、准备环境和测试等一系列工作都非常艰巨,而且很耗时。但使用编译时编程,这部分头疼的工作都可以省略。

没有消息的静态断言

你可能认为,我们已经有了 static_assert(..),可以在编译时进行检查。而如今,断言机制甚至不需要错误消息。这样,代码看上去会更加清晰。

static_assert(false);

if constexpr

我最喜欢的一个语句!我们可以利用 if constexpr 编写一些代码,这些代码可以根据编译时的条件,有选择地进行实例化。

template<typename T>auto length(const T& value) noexcept {if constexpr (std::integral::value) { // is numberreturn value;}else {return value.length();}}int main() noexcept {int a = 5;std::string b = "foo";std::cout << length(a) << ' ' << length(b) << '\n'; // Prints "5 3"}

在 C++17 之前,上面这段代码需要编写两个不同的函数,分别用于字符串和整数输入,如下所示。

int length(const int& value) noexcept {return value;}std::size_t length(const std::string& value) noexcept {return value.length();

constexpr lambda

如果你也喜欢在代码中使用 lambda 表达式,那么肯定会喜欢这个功能。此外,Lambdas 的调用也可以采用直接声明为 constexpr 的形式。

auto identity = [](int n) constexpr { return n; };static_assert(identity(123) == 123);

(3)语法糖

在 C++17 中,有一些功能可以帮助你编写更漂亮的代码。即使它们的存在对运行时性能没有明显的影响,但你会很喜欢它们。

折叠表达式

如果你有过使用可变参数模板来编写具有可变输入或迭代次数的递归算法的经历,那么就可能遇到必须为该可变参数模板函数实现终止符的问题。例如,下面的代码是用 C++11 编写的,作用是累加给定的数字。

int sum() { return 0; } // Termination functiontemplate<typename ...Args>int sum(const int& arg, Args... args) {return arg + sum(args...);}

如果我们没有实现不接受任何输入的终止符,这段代码将无法通过编译。但有了折叠表达式,你就不必实现终止符了,而代码看上去也更好,如下所示。

template<typename ...Args>int sum(Args&&... args) {return (args + ...);}

嵌套命名空间

不知道为什么 C++ 委员会以前没有想到这一点。无需多说,分别看下面 C++11 和 C++17 中嵌套命名空间的定义,你就能发现区别。

// C++11namespace A {namespace B {namespace C {int i;}}}// C++17namespace A::B::C {int i;}

加强版的条件语句

如果所有条件语句都像 for 语句一样具有初始化,那是不是更强大?在 C++17 中,条件语句也增加了初始化部分。

这是迄今为止我所见过的最强大的功能之一,因为你无需在输入一系列 if-else 语句或 switch-case 之前,编写一堆局部变量。

if (int i = 4; i % 2 == 0) {cout << i << " is even number" << endl;}switch (int i = rand() % 100; i) {default:cout << "i = " << i << endl;break;}

内联变量

在 C++17 之前,我们必须在源文件中实例化类内静态变量。如今,你可以使用内联变量将声明和初始赋值合并到类定义中,如下所示。

struct BabaMrb {static const int value = 10;static inline std::string className = "Hello Class";}

(4)其他特性

C++17 中还有许多我不知道如何归类的的其他特性。下面,我们来逐一介绍。

复制省略

复制省略(Copy elision),即返回值优化,是大多数编译器为防止在某些情况下出现额外副本而实现的优化。从 C++17 开始,直接返回对象时必然会触发复制省略。在某些情况下,即使只有一次复制操作也会影响系统的性能,例如对实时性有严格要求的系统。遇到这种情况,我们最好确保避免复制,以免降低系统性能。

struct C {C() { std::cout << "Default constructor" << std::endl; }C(const C&) { std::cout << "Copy constructor" << std::endl; }};C f() {return C();  // Definitely performs copy elision}C g() {C c;return c;    // May perform copy elision}int main() {C obj = f(); // Copy constructor isn't called}

共享互斥锁

在使用共享互斥锁后,我们就可以按需读取对象而无需加锁,而写调用可以照往常一样使用常规互斥锁来锁定对象。共享互斥锁可以加快只读访问操作的速度,因为读取操作可以同步进行。

硬件干涉大小

这个新的库功能可以帮助你在编译期间确定 L1 缓存行的大小。有了这个功能,你就可以根据 L1 缓存行的大小调整结构、缓冲区等。我在使用 C++11 为 ARM Cortex-A9 内核实现低级裸机 DMA 驱动程序时就会用到这个功能,因为在编写这些代码时,我需要手动管理高速缓存和主内存之间的一致性。

尽管此功能非常强大,但直到版本 12 才在所有版本的 GCC 中实现,因此很可能你当前的编译器并不支持。如下代码是一个示例,可以帮助你更好地理解这个功能。

#ifdef __cpp_lib_hardware_interference_size // Undefined prior to C++17using std::hardware_constructive_interference_size;using std::hardware_destructive_interference_size;#else// 64 bytes on x86-64 │ L1_CACHE_BYTES │ L1_CACHE_SHIFT │ __cacheline_aligned │ ...constexpr std::size_t hardware_constructive_interference_size   = 64;constexpr std::size_t hardware_destructive_interference_size    = 64;#endifstruct alignas(hardware_constructive_interference_size) OneCacheLiner { // occupies one cache linestd::atomic_uint64_t x{};std::atomic_uint64_t y{};};


总结

与 C++14 不同,C++17 引入了许多新特性。其中一些功能对嵌入式系统开发非常有帮助。

不同产品之间,嵌入式设备的计算能力差异很大。由于 CPU 性能、缺乏编译器支持、验证必要性等多种原因,我选择的某些功能可能不适用于你的固件。总体而言,迁移到 C++17 可能需要花费大量的时间和精力,请认真考虑是否需要迁移。

版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

关注我的微信公众号,回复“加群”按规则加入技术交流群。


点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。

李肖遥 公众号“技术让梦想更伟大”,作者:李肖遥,专注嵌入式,只推荐适合你的博文,干货,技术心得,与君共勉。
评论 (0)
  • 全球领先的光学解决方案供应商艾迈斯欧司朗(SIX:AMS)近日宣布,凭借AS1163独立智能驱动器(SAID)成为中国领先的智能集成系统产品汽车制造商宁波福尔达智能科技股份有限公司(“福尔达”)环境动态照明应用的关键供应商。此次合作标志着汽车技术发展的一个重要时刻,充分展现了AS1163在优化动态照明应用系统成本方面的多功能性和先进性能。该产品支持传感器集成,拥有专为车顶照明设计的超薄外形,并能提升车内照明系统的性能。AS1163是一款先进的智能LED驱动器,能够与开放系统协议(OSP)网络无缝
    艾迈斯欧司朗 2025-03-20 14:26 131浏览
  • 如同任何对我们工作方式的改变,新的工作方式必然会遇到许多必须面对的挑战。如果不解决组织在实施精益六西格玛过程中面临的障碍以及如何克服它们的问题,那么关于精益六西格玛的讨论就不算完整。以下列举了组织在成功实施精益六西格玛时常见的几个障碍,以及克服它们的方法:1)对精益六西格玛方法论缺乏理解。抵触情绪通常源于对精益六西格玛方法论的不了解,以及不相信它能真正发挥作用。这种情况在所有层级的人员中都会出现,包括管理层。虽然教育培训可以帮助改善这一问题,但成功的项目往往是打消疑虑的最佳方式。归根结底,这是一
    优思学院 2025-03-20 12:35 128浏览
  • 为有效降低人为疏失导致交通事故发生的发生率,各大汽车制造厂及系统厂近年来持续开发「先进驾驶辅助系统」ADAS, Advanced Driver Assistance Systems。在众多车辆安全辅助系统之中,「紧急刹车辅助系统」功能(AEB, Autonomous Emergency Braking)对于行车安全性的提升便有着相当大的帮助。AEB透过镜头影像模块与毫米波雷达感测前方目标,可在发生碰撞前警示或自动刹车以降低车辆损伤以及乘员伤害。面临的挑战以本次分享的客户个案为例,该车厂客户预计在
    百佳泰测试实验室 2025-03-20 15:07 134浏览
  • 本文内容来自微信公众号【工程师进阶笔记】,以工程师的第一视角分析了飞凌嵌入式OK3506J-S开发板的产品优势,感谢原作者温老师的专业分享。前两周,有一位老朋友联系我,他想找人开发一款数据采集器,用来采集工业现场的设备数据,并且可以根据不同的业务场景,通过不同的接口把这些数据分发出去。我把他提的需求总结了一下,这款产品方案大概有以下功能接口,妥妥地一款工业网关,在网上也能找到很多类似的产品方案,为啥他不直接买来用?再跟朋友深入地聊了一下,他之所以联系我,是因为看到我在公众号介绍过一款由飞凌嵌入式
    飞凌嵌入式 2025-03-20 11:51 139浏览
  • PCIe 5.0应用环境逐步成形,潜在风险却蠢蠢欲动?随着人工智能、云端运算蓬勃发展,系统对于高速数据传输的需求不断上升,PCI Express(PCIe)成为服务器应用最广的传输技术,尤其在高效能运算HPC(High Performance Computing)及AI服务器几乎皆导入了最新的PCIe 5.0规格,使得数据传输的双向吞吐量达到了128GB/s,让这两类的服务器能够发挥最大的效能。不过随着PCIe 5.0的频率达到16GHz,PCB板因为高频而导致讯号衰减加剧的特性,使得厂商面临很
    百佳泰测试实验室 2025-03-20 13:47 133浏览
  •         在当今电子设备高度集成的时代,电路保护显得尤为重要。TVS管(瞬态电压抑制二极管)和压敏电阻作为一种高效的电路保护器件,被广泛应用于各种电子设备中,用以吸收突波,抑制瞬态过电压,从而保护后续电路免受损坏。而箝位电压,作为TVS管和压敏电阻的核心参数之一,直接关系到其保护性能的优劣。箝位电压的定义        箝位电压指瞬态保护器件(如TVS二极管、压敏电阻)在遭遇过压时,将电路电压限制在安全范围内的
    广电计量 2025-03-20 14:05 116浏览
  • 近日,保定飞凌嵌入式技术有限公司(以下简称“飞凌嵌入式”)携手瑞芯微电子股份有限公司(以下简称“瑞芯微”)正式加入2025年全国大学生嵌入式芯片与系统设计竞赛(以下简称“嵌入式大赛”),并在应用赛道中设立专属赛题。本次嵌入式大赛,双方选用基于瑞芯微RK3588芯片设计的ELF 2开发板作为参赛平台,旨在通过此次合作,促进产教融合,共同推动嵌入式系统创新人才的培养。全国大学生嵌入式芯片与系统设计竞赛是一项A类电子设计竞赛,同时也是被教育部列入白名单的赛事,由中国电子学会主办,是学生保研、求职的公认
    飞凌嵌入式 2025-03-20 11:53 109浏览
  • 家电“以旧换新”政策的覆盖范围已从传统的八大类家电(冰箱、洗衣机、电视、空调、电脑、热水器、家用灶具、吸油烟机)扩展至各地根据本地特色和需求定制的“8+N”新品类。这一政策的补贴再叠加各大电商平台的优惠,家电销售规模显著增长,消费潜力得到进一步释放。晶尊微方案为升级换代的智能家电提供了高效且稳定的触摸感应和水位检测功能,使得操作更加便捷和可靠!主要体现在:水位检测1健康家电:养生壶、温奶器、加湿器的缺水保护安全2清洁电器:洗地机、扫地机器人的低液位和溢液提醒3宠物家电:宠物饮水机的缺水提醒/满水
    ICMAN 2025-03-20 15:23 183浏览
  • 流感季急诊室外彻夜排起的长队,手机屏幕里不断闪烁的重症数据,深夜此起彼伏的剧烈咳嗽声——当病毒以更狡猾的姿态席卷全球,守护健康的战争早已从医院前移到每个人的身上。在医学界公认的「72小时黄金预警期」里,可穿戴设备闪烁的光芒正穿透皮肤组织,持续捕捉血氧浓度、心率变异性和体温波动数据。这不是科幻电影的末日警报,而是光电传感器发出的生命预警,当体温监测精度精确到±0.0℃,当动态血氧检测突破运动伪影干扰……科技正在重新定义健康监护的时空边界。从智能手表到耳机,再到智能戒指和智能衣物,这些小巧的设备通过
    艾迈斯欧司朗 2025-03-20 15:45 214浏览
  • 贞光科技代理的品牌-光颉科技高精密薄膜电阻凭借0.01%的超高精度,在AI服务器电源模块中实现了精确电压分配、优化功率因数和减少热损耗,显著提升系统能效和可靠性。在当今的数字时代,人工智能(AI)服务器已成为数据中心的核心。随着AI应用的激增,服务器的性能和能效需求也在不断提高。电源模块作为服务器的关键组件,其性能直接影响整个系统的效率和可靠性。本文将探讨光颉科技高精密薄膜电阻,特别是其0.01%的精度,如何在AI服务器电源模块中提升能效。电源模块在AI服务器中的重要性电源模块负责将输入电源转换
    贞光科技 2025-03-20 16:55 185浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦