当前位置: 首页 > news >正文

3个令人惊叹的C++17功能,让代码变得更简洁

一、简介

C++17 为 C++ 语言带来了许多功能。本文深入研究其中的三个,它们有助于使编码更容易、更简洁、更直观和正确。

本文从结构化绑定开始。结构化绑定适用于许多情况,本文介绍几种情况可以使代码更简洁、更简单。介绍模板参数推导,可以删除习惯键入的模板参数。最后介绍用“选择初始化”更好控制对象范围,并允许定义它们所属的值。

二、结构化绑定

结构化绑定允许一次性定义多个对象,其方式比以前的 C++ 版本更自然。从 C++11 到 C++17,这个概念本身并不新鲜。C++17以前,始终可以从函数返回多个值并使用std::tie

例如:

展开

代码语言:C++

自动换行

AI代码解释

std::tuple<char, int, bool> mytuple() { char a = 'a'; int i = 123; bool b = true; return std::make_tuple(a, i, b); }

这返回三个不同类型的变量。要从 C++17 之前调用函数访问这些函数,要如下内容:

代码语言:C++

自动换行

AI代码解释

char a; int i; bool b; std::tie(a, i, b) = mytuple();

其中必须在用前定义变量并预先了解类型。

但是使用结构化绑定,可以简单执行为:

代码语言:C++

自动换行

AI代码解释

auto [a, i, b] = mytuple();

这是一种更好的语法,几乎尽可能用auto,与现代C++样式也一致。

那么,什么可以与结构化绑定初始化一起使用呢?基本上任何复合类型structpairtuple。让我们看看它可能有用的几种情况。

2.1、返回复合对象

这是一次性将复合类型的各个部分(如structpair等)分配给不同变量并自动分配正确类型的简单方法。例如,如果把数据插入到std::map中,那么结果是一个:std::pair

代码语言:C++

自动换行

AI代码解释

std::map<char,int> mymap; auto mapret = mymap.insert(std::pair('a', 100));

可能有人想知道上面的代码为什么没有明确说明配对的类型,这就是后面要讲的C++17 中的模板参数推导了,请接着往下阅读。因此,为了确定数据插入是否成功,可以从插入方法返回的内容mapret中提取second信息。

问题在于,读者应该需要查找什么才能确定是否插入成功。但是使用结构化绑定,这将变成:

代码语言:C++

自动换行

AI代码解释

auto [itelem, success] = mymap.insert(std::pair(’a’, 100)); If (!success) { // Insert failure }

其中itelem是元素的迭代器,success的类型为booltrue用于表示插入成功。变量的类型是从赋值中自动推断出来的——这在阅读代码时更有意义。

选择初始化作为本文最后一节的内容,这里先睹为快,由于 C++17 现在具有选择初始化,那么我们可以将其编写为:

代码语言:C++

自动换行

AI代码解释

if (auto [itelem, success] = mymap.insert(std::pair(‘a’, 100)); success) { // Insert success }

这个稍后会详细介绍。

2.2、遍历复合集合

结构化绑定也适用于范围。因此,考虑到前面的mymap定义,在 C++17 之前是使用如下所示的代码对其进行迭代:

代码语言:C++

自动换行

AI代码解释

for (const auto& entry : mymap) { // Process key as entry.first // Process value as entry.second }

或者,更明确地说:

代码语言:C++

自动换行

AI代码解释

for (const auto& entry : mymap) { auto& key = entry.first; auto& value = entry.second; // Process entry }

但是结构化绑定允许更直接地编写它:

代码语言:C++

自动换行

AI代码解释

for (const auto&[key, value] : mymap) { // Process entry using key and value }

变量keyvalue的用法比entry.firstentry.second更具指导意义,并且不需要额外的变量定义。

2.3、直接初始化

但是,由于结构化绑定可以从tuplepair等进行初始化,我们可以以这种方式进行直接初始化吗?

是的,我们能。比如:

代码语言:C++

自动换行

AI代码解释

auto a = ‘a’; auto i = 123; auto b = true;

它将变量a的初始值定义为char 类型的ai初始值为int类型的123,以及b初始值为bool的类型的true

使用结构化绑定,可以写成:

代码语言:C++

自动换行

AI代码解释

auto [a, i, b] = tuple(‘a’, 123, true); // With no types needed for the tuple!

这将变量aib定义得就像使用了上面的单独定义一样。

这真的是对之前定义的改进吗?已经在一行中完成了本来需要三行才能完成的工作,但为什么要这样做呢?考虑以下代码:

代码语言:C++

自动换行

AI代码解释

{ istringstream iss(head); for (string name; getline(iss, name); ) // Process name }

issname两者都只在for块内使用,但必须在for语句之外和它自己的块内声明,以便将范围限制在所需的范围内。

这很奇怪,因为iss是属于for循环。始终可以初始化相同类型的多个变量。例如:

代码语言:C++

自动换行

AI代码解释

for (int i = 0, j = 100; i < 42; ++i, --j) { // Use i and j }

但我们想写但不能写的是:

代码语言:C++

自动换行

AI代码解释

for (int i = 0, char ch = ‘ ‘; i < 42; ++i) { // Does not compile // Use i and ch }

使用结构化绑定,我们就可以这样编写:

代码语言:C++

自动换行

AI代码解释

for (auto[iss, name] = pair(istringstream(head), string {}); getline(iss, name); ) { // Process name }

代码语言:C++

自动换行

AI代码解释

for (auto[i, ch] = pair(0U, ‘ ‘); i < 42; ++i) { // The 0U makes i an unsigned int // Use i and ch }

这允许根据需要在for语句的范围内定义变量issname(以及ich),并且还可以自动确定它们的类型。

ifswitch语句也是如此,它现在在C++ 17中采用可选的选择初始化(见下文)。例如:

代码语言:C++

自动换行

AI代码解释

if (auto [a, b] = myfunc(); a < b) { // Process using a and b }

注意,并不能用结构化绑定做所有事情,试图让它们适应每种情况会使代码更加复杂。比如:

代码语言:C++

自动换行

AI代码解释

if (auto [box, bit] = std::pair(std::stoul(p), boxes.begin()); (bit = boxes.find(box)) != boxes.end()){ // Process if using both box and bit variables }此处box变量被定义为类型unsigned long,并且具有从stoul(p)返回的初始值。对于那些不熟悉它的人来说,stoul()是一个函数,它以类型作为其第一个参数(还有其他可选参数<string>- 包括std::string_base),并将其内容解析为指定基数的整数(默认为 10),该函数作为无符号长整型值返回。

http://www.jsqmd.com/news/450514/

相关文章:

  • Spring Boot + Spring AI快速体验
  • Redis集群模式
  • 如何搭建一个聊天机器人?#3 初步了解koishi、napcat以及onebot
  • 锦囊专家:2025中国企业数智化转型典范案例集 2026
  • 手机也能玩AI换脸?云端部署Roop-Unleashed保姆级教程
  • 免费好用的论文查重网站推荐
  • 群晖Synology Directory Server批量导入用户避坑指南:为什么你的TXT文件总是导入失败?
  • 读懂“社稷为重,君为轻”:真正的忠臣,从不是皇帝的奴才
  • rust web框架actix和axum比较
  • AIChat聊天助手:把 AI 助手“嵌进”你的业务系统
  • 【VMD+Gromacs】用 VMD 玩转分子动力学可视化
  • Spring Boot 各种事务操作实战(自动回滚、手动回滚、部分回滚)
  • 强化学习,第五部分:时间差分学习
  • Java Web 校车调度管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】
  • “印度人参“药效之“醉茄内酯“内酯环的生物合成途径解析
  • 哈尔滨汽车音响改装 大众揽镜丹麦丹拿232、丹拿212、阿尔派R120-12音响改装升级 全车隔音降噪 哈尔滨消费者满分好评店铺-博士达汽车音响作品 - 木火炎
  • 【2025最新】基于SpringBoot+Vue的校园便利平台管理系统源码+MyBatis+MySQL
  • 【C++基础篇】学习C++就看这篇--->泛型编程之模板
  • 2026搪瓷拼装罐优质品牌推荐指南 - 优质品牌商家
  • 2026年3月,评测揭秘行业口碑好的仿古拉丝机品牌,木纹拉丝机/地板拉丝机/底漆砂光机,拉丝机实力厂家口碑排行 - 品牌推荐师
  • 又一家独角兽冲刺港股:仓储机器人“军备竞赛“进入决赛圈
  • 深度学习驱动的桥梁裂缝检测:从原理到实践
  • 从零开始打造你的专属NAS
  • 76_Spring AI 干货笔记之 MCP 服务器注解 - 教程
  • 上海正规防水公司哪家强?深耕本土14年的专业选择 - shruisheng
  • 基于Django+Vue+MySQL的花卉电商平台系统(含完整源码与12000字详细开发文档)
  • 强化学习,第六部分:n 步引导
  • 下面是 TypeScript + ESModule 版本的最小示例,和你项目更接近。
  • 无人机巡检图像分析实战:基于深度学习的电线杆与铁塔智能识别与缺陷检测
  • 中兴通讯年营收1339亿:扣非后净利33.7亿同比降45% 派息20亿