最常使用的现代C++新特性介绍

现代 C++泛指的是从 C++11 之后的 C++标准. 从 C++11 开始, C++标准委员会实行班车制, 没三年发布一个新版本, 如果一个功能在新版本发布之前已经准备好, 则可以加入该版本中, 否则延后到下一个版本.

语言核心

自 C++11 开始, 语言语法层面加了许多语法糖, 还有增加了一些新语法.使得 C++语言更加简洁, 更加易读, 同时更不容易出错.

auto自动类型推导

auto允许程序员在声明变量的时候让编译器自动推导变量的类型, 而不需要显式声明变量的类型.

#include <string>int main() {auto x = 1;auto s = "Hello";auto str = std::string("World");// C++11 之前std::string::iterator it1 = str.begin();// C++11 之后auto it = str.begin();
}

if/switch中声明变量

增加了语法糖, 允许在if/switch中声明一个变量, 这样一方面简化写法, 另一方面限制了变量的可见范围, 提高安全性.

#include <fcntl.h>
#include <unistd.h>#include <iostream>char getOption() { return 'y'; }
int main() {if (auto ret = open("output.txt", O_RDONLY); ret != -1) {std::cout << "open file success" << std::endl;close(ret);}switch (auto c = getOption(); c) {case 'y':[[fallthrough]];case 'Y':std::cout << "yes" << std::endl;break;default:break;}
}

Range based for loop

增加了语法糖, 可以简化for循环写法, 并同时提升安全性.

#include <vector>
#include <print>int main() {// 遍历 vectorstd::vector v{1, 2, 3};for (auto num : v) {std::println("{}", num);}// 遍历数组int array[] = {1, 2, 3};for (auto num : array) {std::println("{}", num);}
}

结构化绑定

#include <map>
#include <print>
#include <string>int main() {std::map<std::string, int> map = {{"a", 1}, {"b", 2}};for (auto [key, value] : map) {std::println("{}:{}", key, value);}// bind to tupleauto tuple = std::make_tuple(1, 2, 3);auto [a, _, c] = tuple;std::println("a={}", a);
}

统一初始化

支持通过花括号{}初始化任意类型的变量. 对泛型编程的场景帮助很大.

#include <string>
#include <vector>int main() {int a{0};std::string str{"Hello"};struct S {std::string name;float num;S(std::string s, float f) : name(s), num(f) {}};S s1{"Alan", 2.7};std::vector<S> v{s1, {"Bob", 85.9}};
}

进一步阅读: C++ 类成员初始化发展历程(从 C++11 到 C++20)

移动语义

移动语义是 C++11 引入的, 主要用来减少不必要的拷贝, 提升性能. 对于一些临时变量, 或者说不会再使用的变量, 则可以采用移动语义来减少拷贝.

#include <string>
#include <vector>std::string GetStr() { return "Hello"; }
int main() {std::vector<std::string> vec;auto s = GetStr();vec.emplace_back(s);             // copyvec.emplace_back(s + "World");   // movevec.emplace_back(GetStr());      // movevec.emplace_back(std::move(s));  // movereturn 0;
}

进一步阅读: C++ 必知必会: 移动语义(Move Semantics)

lambdas 表达式

在编程中经常会用到一些临时函数或者工具函数, 只在局部使用, 并且功能简单. 以往的方式会造成声明语使用位置相距比较远, 影响可读性. lambda 表达式可以允许我们定义一个临时的函数, 并且可以省略函数名.

#include <algorithm>
#include <string>
#include <vector>int main() {struct Record {std::string s1;std::string s2;};std::vector<Record> v = {{"A", "1"}, {"B", "0"}, {"a", "2"}};std::sort(v.begin(), v.end(), [](const auto& p1, const auto& p2) {return p1.s1 < p2.s1 || (p1.s1 == p2.s1 && p1.s2 < p2.s2);});
}

进一步阅读: C++ Lambda 表达式: 简洁与高效的完美结合

constexpr

constexpr 用来声明一个常量表达式, 可以在编译期计算出结果, 并且可以避免运行时计算. 相比起宏定义, constexpr 更加类型安全, 因为本质上讲define是字符串替换, 没有类型检查.

#define SIZE 64
constexpr int size = 64;

进一步阅读:

  • C++ constexpr, consteval 和 constinit 简要介绍
  • C++ 中的 const 和 constexpr: 深入对比与最佳实践

标准库

多线程编程

  1. 线程(std::thread/std::jthread). C++11 引入了线程, 并在 C++20 加入了满足 RAII 要求的jthread. 详情参考: C++20 std::jthread 完全指南 - 简化多线程编程与线程管理
  2. 原子变量(std::atomic): 是一种特殊的变量类型, 它支持原子操作, 这些操作在多线程环境下是不可分割的, 也就是不会被其他线程的操作打断. 这有助于避免多线程访问共享资源时产生的数据竞争问题, 保证数据安全. 进一步阅读: Modern C++ 中的 std::atomic 简介
  3. 互斥锁(std::mutex): 是一种同步机制, 它保证多个线程对共享资源的访问是互斥的. 进一步阅读: 现代 C++锁介绍
  4. Latch 和 Barrier: 线程同步机制, 它们可以确保多个线程在某个事件发生之前不会继续执行. 进一步阅读: C++ Latch 和 Barrier: 新手指南

工具类

  1. string_view: 轻量级视图, 它只包含对数据的引用, 不包含数据本身. 可以简单理解为包含了字符串的指针和长度. 详情参考: 深入理解 C++ std::string_view — 高效字符串操作的利器
  2. optional: 顾名思义, 这个工具包含的数据可能为空, 通常用于表示一个可选的值. 进一步阅读: 现代 C++ 必备知识: 解锁 std::optional, std::variant 和 std::any
  3. variant: 是对于传统的union的一种更安全的替代. 可以保存多个类型的值, 但是只能存储其中一个.
  4. any: any相对于一个特定类型的值就好比void *对于一种特定类型的指针. any可以被赋值为任何类型, 但是只能读取为原始类型.
  5. expected: 对于返回值+错误提示的一种通用表示, 在成功的情况下返回一个可用的值, 否则返回对应的错误类型. 进一步阅读: 解读 C++23 std::expected 函数式写法

总结

本文是对现代 C++新特性的一个简单介绍, 只包含了笔者认为的常用特性, 对细节感兴趣的朋友请查阅相关资料进一步阅读. 这里也有我按版本整理的新特性介绍: 现代 C++, 有兴趣的读者可以进一步浏览.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/73849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL Server:当在删除数据库时因为存在触发器而无法删除

当在删除数据库时因为存在触发器而无法删除&#xff0c;你可以通过禁用触发器来解决这个问题。下面为你介绍在 SQL Server 里禁用和启用触发器的方法。 禁用数据库中所有表的触发器 你可以使用系统视图 sys.triggers 来查询数据库里所有的触发器&#xff0c;然后生成禁用这些…

【Linux篇】进程入门指南:操作系统中的第一步

步入进程世界&#xff1a;初学者必懂的操作系统概念 一. 冯诺依曼体系结构1.1 背景与历史1.2 组成部分1.3 意义 二. 进程2.1 进程概念2.1.1 PCB&#xff08;进程控制块&#xff09; 2.2 查看进程2.2.1 使用系统文件查看2.2.2 使⽤top和ps这些⽤⼾级⼯具来获取2.2.3 通过系统调用…

销售易vs纷享销客:制造行业CRM选型深度解析

“以客户为中心”&#xff0c;顾名思义就是指让客户贯穿企业市场、研发、生产、销售、服务全流程&#xff0c;以客户需求为导向进行经营。CRM作为企业数字化建设基础设施&#xff0c;在企业高质量发展进程中扮演着重要角色。在众多CRM解决方案中&#xff0c;腾讯旗下CRM销售易凭…

【JavaScript】九、JS基础练习

文章目录 1、练习&#xff1a;对象数组的遍历2、练习&#xff1a;猜数字3、练习&#xff1a;生成随机颜色 1、练习&#xff1a;对象数组的遍历 需求&#xff1a;定义多个对象&#xff0c;存数组&#xff0c;遍历数据渲染生成表格 let students [{ name: 小明, age: 18, gend…

代码随想录day31 贪心part05

56.合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输入&#xff1a;in…

《C++11:通过thread类编写C++多线程程序》

关于多线程的概念与理解&#xff0c;可以先了解Linux下的底层线程。当对底层线程有了一定程度理解以后&#xff0c;再学习语言级别的多线程编程就轻而易举了。 【Linux】多线程 -&#xff1e; 从线程概念到线程控制 【Linux】多线程 -&#xff1e; 线程互斥与死锁 语言级别的…

c++位运算总结

在C中&#xff0c;位运算是对二进制位进行操作的运算&#xff0c;主要有以下几种&#xff1a; 1. 按位与&#xff08; & &#xff09;&#xff1a;两个操作数对应位都为1时&#xff0c;结果位才为1&#xff0c;否则为0。例如 3 & 5 &#xff0c; 3 二进制是 0000 0011…

1.1 计算机网络的概念

首先来看什么是计算机网络&#xff0c;关于计算机网络的定义并没有一个统一的标准&#xff0c;不同的教材有 不同的说法&#xff08;这是王道书对于计算机网络的定义&#xff09;&#xff0c;我们可以结合自己的生活经验去体会这个 定义。 可以用不同类型的设备去连接计算机网络…

用LLama factory时报类似Process 2504721 got signal: 1的解决方法

之前用nohup来远程跑LLama factory微调脚本&#xff0c;是没有问题的&#xff0c;但今天发现运行类似下面这个命令时&#xff0c; nohup llamafactory-cli train examples/train_qlora/qwen_lora.yaml 只要一关闭ssh session&#xff0c;就会终止训练&#xff0c;报类似&…

python常用内置时间函数+蓝桥杯时间真题

1.time 1.1 time.time() 时间戳指&#xff1a;1970年1月1日开始到现在所经过的秒数 import time print(time.time()) # 输出可得1970年1月1日开始到执行此代码所经过的秒数 1.2 time.localtime() 返回一个当前时间的时间对象&#xff0c;具体信息&#xff0c;并且可以单独…

一个用 C 语言打印出所有三位数水仙花数的程序

水仙花数&#xff08;Narcissistic number&#xff09;是指一个三位数&#xff0c;其各位数字的立方和等于该数本身。例如&#xff1a;153 是一个水仙花数&#xff0c;因为 (1^3 5^3 3^3 153)。 以下是一个用 C 语言打印出所有三位数水仙花数的程序&#xff1a; 代码实现 …

利用 VSCode 配置提升 vibe coding 开发效率

利用 VSCode 配置提升 vibe coding 开发效率 Vibe Coding&#xff08;氛围编程&#xff09;是一种基于AI的编程方法&#xff0c;其核心在于通过自然语言描述软件需求&#xff0c;再由大规模语言模型&#xff08;LLM&#xff09;自动生成代码&#xff0c;从而实现对传统手写编程…

练习题:110

目录 Python题目 题目 题目分析 需求理解 关键知识点 实现思路分析 代码实现 代码解释 函数定义&#xff1a; 计算值的总和&#xff1a; 测试函数&#xff1a; 运行思路 结束语 Python题目 题目 定义一个函数&#xff0c;接受一个字典作为参数&#xff0c;返回字…

处理 Linux 信号:进程控制与异常管理的核心

个人主页&#xff1a;chian-ocean 文章专栏-Linux 前言&#xff1a; 在 Linux 操作系统中&#xff0c;信号是用于进程间通信的一种机制&#xff0c;能够向进程发送通知&#xff0c;指示某些事件的发生。信号通常由操作系统内核、硬件中断或其他进程发送。接收和处理信号是 Li…

通信协议之串口

文章目录 简介电平标准串口参数及时序USART与UART过程引脚配置 简介 点对点&#xff0c;只能两设备通信只需单向的数据传输时&#xff0c;可以只接一根通信线当电平标准不一致时&#xff0c;需要加电平转换芯片&#xff08;一般从控制器出来的是信号是TTL电平&#xff09;地位…

Unity编辑器功能及拓展(1) —特殊的Editor文件夹

Unity中的Editor文件夹是一个具有特殊用途的目录&#xff0c;主要用于存放与编辑器扩展功能相关的脚本和资源。 一.纠缠不清的UnityEditor 我们Unity中进行游戏构建时&#xff0c;我们经常遇到关于UnityEditor相关命名空间丢失的报错&#xff0c;这时候&#xff0c;只得将报错…

工具类-csv文件导入数据库思路

首先&#xff0c;让我们来看下数据库建表语句&#xff1a; CREATE TABLE behavior_reports (id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 报告ID,report_type VARCHAR(50) NOT NULL COMMENT 报告类型(daily, weekly, monthly),start_date DATE NOT NULL COMMENT 开始日期,e…

软件工程之软件开发模型(瀑布、迭代、敏捷、DevOps)

1. 瀑布模型&#xff08;Waterfall Model&#xff09; 定义与流程 瀑布模型是线性顺序的开发流程&#xff0c;包含需求分析、设计、编码、测试、维护等阶段&#xff0c;每个阶段完成后才能进入下一阶段&#xff0c;类似“瀑布流水”逐级推进。 核心特点 严格阶段划分&#…

FreeRTOS与RT-Thread内存分配对比分析

一、动态内存分配策略 ​FreeRTOS ​分配算法多样性&#xff1a;提供5种动态内存管理算法&#xff08;heap_1至heap_5&#xff09;&#xff0c;覆盖从简单到复杂的场景。例如&#xff1a; heap_1&#xff1a;仅支持分配不支持释放&#xff0c;适用于固定任务栈分配。heap_4&…

202519 | Mybatis-Plus

快速入门 MyBatis-Plus&#xff08;简称 MP&#xff09;是 MyBatis 的增强工具&#xff0c;它在 MyBatis 的基础上只做增强不做改变&#xff0c;简化了开发&#xff0c;提高了效率。以下是 MyBatis-Plus 的快速入门指南&#xff0c;帮助您快速上手使用。 1. 环境准备 JDK&…