C++进阶:C++11相关
◆博主名称少司府欢迎来到少司府的博客☆*: .. o(≧▽≦)o ..:*☆⭐数据结构系列个人专栏初阶数据结构_少司府的博客-CSDN博客⭐C基础个人专栏C初阶_少司府的博客-CSDN博客⭐琢玉成器终有时笔底生花夺锦归目录1. 列表初始化1.1 C98中的{}1.2 C11中的{}1.3 C11中的initializer_list2.右值引用和移动语义2.1 右值和左值2.1.1 左值2.1.2 右值2.2 左值引用和右值引用2.3 延长生命周期2.4 左值和右值的参数匹配2.5 右值引用和移动语义的使用场景2.5.1 左值引用使用场景2.5.2 右值引用和移动语义使用场景3. 类型分类4. 引用折叠和完美转发4.1 引用折叠4.2 完美转发1. 列表初始化1.1 C98中的{}在C98中利用{}初始化的情况有两种结构体的初始化和数组的初始化。struct Point { int _x; int _y; }; int main() { int arr[]{1,2,3,4,5}; Point p{1,2}; return 0; }1.2 C11中的{}1、C11以后试图实现一切对象皆可用{}初始化{}初始化也叫做列表初始化。2、内置类型和自定义类型都可以列表初始化自定义类型列表初始化本质就是类型转换。// C11⽀持的 // 内置类型⽀持 int x1 { 2 }; // ⾃定义类型⽀持 // 这⾥本质是⽤{ 2025, 1, 1}构造⼀个Date临时对象 // 临时对象再去拷⻉构造d1编译器优化后合⼆为⼀变成{ 2025, 1, 1}直接构造初始化d1 Date d1 { 2025, 1, 1 };3、列表初始化const引用的临时对象。// 这⾥d2引⽤的是{ 2024, 7, 25 }构造的临时对象 ,临时对象具有常性 const Date d2 { 2024, 7, 25 };4、需要注意的是C98⽀持单参数类型转换时也可以不⽤{}Date d3 { 2025 }; // C11 Date d4 2025; // C985、在列表初始化的时候可以省略// 可以省略掉 Point p1{ 1, 2 }; int x2{ 2 }; Date d6{ 2024, 7, 25 }; const Date d7{ 2024, 7, 25 }; // 不⽀持只有{}初始化才能省略 // Date d8 2025;6、在多参数类型构造对象的时候列表初始化会方便很多。vectorDate v; v.push_back(d1); v.push_back(Date(2025, 1, 1)); // ⽐起有名对象和匿名对象传参这⾥{}更有性价⽐ v.push_back({ 2025, 1, 1 });1.3 C11中的initializer_listC11提供一个类模板initializer_list这是它的文档initializer_list - C Reference有了initializer_list我们可以实现n个值去初始化构造一个容器对象// 构造拷贝构造优化 vectorint v1 { 1,2,3,4 }; vectorint v2{ 1,2,3,4 }; // 构造两者的构造都是隐式类型转换为initializer_listint类型 vectorint v3({ 1,2,3,4,5 });initializer_list特点{ }内括起来的数据类型是一样的。2.右值引用和移动语义C11之前学习的都是左值引用C11之后增加了右值引用的概念两者本质都是给对象取别名。2.1 右值和左值2.1.1 左值左值是一个表示数据的表达式一般具有持久状态可以取地址可以出现在赋值符号的左右两边const修饰的左值不能更改它的数据但是可以取地址。// 左值可以取地址 // 以下的p、b、c、*p、s、s[0]就是常⻅的左值 int* p new int(0); int b 1; const int c b; *p 10; string s(111111); s[0] x; double x 1.1, y 2.2;如图常见的左值一般包括变量名、计算表达式*p、p等、函数调用表达式s[ 0 ]返回类型是引用Ref可以修改。2.1.2 右值右值也是一个表示数据的表达式一般不具有持久状态不能取地址只能出现在赋值符号的右边。// 以下⼏个10、x y、fmin(x, y)、string(11111)都是常⻅的右值 10; x y; fmin(x, y); string(11111);如图常见的右值包括字面量常量、表达式返回的临时对象、匿名对象、函数的非引用返回等。2.2 左值引用和右值引用1、左值引用来引用左值右值引用来引用右值// 左值引⽤给左值取别名 int r1 b; int* r2 p; int r3 *p; string r4 s; char r5 s[0]; // 右值引⽤给右值取别名 int rr1 10; double rr2 x y; double rr3 fmin(x, y); string rr4 string(11111);2、左值引用不能直接引用左值但是const左值引用可以引用右值const int rx1 10;3、右值引用不能直接引用左值但是右值引用可以引用move(左值)move的本质就是类型转换左值表达式变成将亡值。move(b); // 不改变b本身的状态 int rrx1 move(b); // move是一个函数模板4、注意变量表达式本身是左值的属性也就是说一个右值引用的变量名本身是左值属性的// 这⾥要注意的是rr1的属性是左值所以不能再被右值引⽤绑定除⾮move⼀下 int r6 rr1; // 普通左值引用 int 只允许绑定左值;rr1 是具名变量表达式rr1属于左值匹配绑定规则编译通过。 // int rrx6 rr1; int rrx6 move(rr1);5、语法上左值引用和右值引用都是取别名不开空间汇编上两者都是指针实现的指令都是一样的。2.3 延长生命周期右值引用和const左值引用都可以延长临时对象的生命周期但是const引用的对象不能被修改。std::string s1 Test; // std::string r1 s1; // 错误不能绑定到左值 const std::string r2 s1 s1; // OK到 const 的左值引⽤延⻓⽣存期 // r2 Test; // 错误不能通过到 const 的引⽤修改 std::string r3 s1 s1; // OK右值引⽤延⻓⽣存期 r3 Test; // OK能通过到⾮ const 的引⽤修改 std::cout r3 \n;2.4 左值和右值的参数匹配1、C98中我们实现一个const左值引用作为参数的函数那么左值右值都可以匹配2、C11之后我们要重载实现对应匹配的函数void f(int x) { std::cout 左值引⽤重载 f( x )\n; } void f(const int x) { std::cout const 的左值引⽤重载 f( x )\n; } void f(int x) { std::cout 右值引⽤重载 f( x )\n; }2.5 右值引用和移动语义的使用场景先给出以下代码class Solution { public: // 传值返回需要拷⻉ string addStrings(string num1, string num2) { string str; int end1 num1.size() - 1, end2 num2.size() - 1; // 进位 int next 0; while (end1 0 || end2 0) { int val1 end1 0 ? num1[end1--] - 0 : 0; int val2 end2 0 ? num2[end2--] - 0 : 0; int ret val1 val2 next; next ret / 10; ret ret % 10; str (0 ret); } if (next 1) str 1; reverse(str.begin(), str.end()); return str; } // 这⾥的传值返回拷⻉代价就太⼤了 vectorvectorint generate(int numRows) { vectorvectorint vv(numRows); for (int i 0; i numRows; i) { vv[i].resize(i 1, 1); } for (int i 2; i numRows; i) { for (int j 1; j i; j) { vv[i][j] vv[i - 1][j] vv[i - 1][j - 1]; } } return vv; } };当前两个函数是实现字符串相加和杨辉三角的逻辑。2.5.1 左值引用使用场景回顾一下左值引用主要使⽤场景是——在函数中左值引⽤传参和左值引⽤传返回值时减少拷⻉同时还可以修改实参和修改返回对象的价值。但是如果遇到这个情况——要返回的对象的作用域只在当前函数栈帧出了作用域就销毁了就不能直接返回左值引用。如上述两个函数。这里就需要用到右值引用来解决这个问题。在C11之前该问题可以靠输出型参数解决void addStrings(const string num1, const string num2, string res) { res.clear(); // 清空原有内容复用内存 int i num1.size() - 1; int j num2.size() - 1; int carry 0; while (i 0 || j 0) { int v1 i 0 ? num1[i--] - 0 : 0; int v2 j 0 ? num2[j--] - 0 : 0; int sum v1 v2 carry; carry sum / 10; res.push_back(sum % 10 0); } if (carry ! 0) { res.push_back(1); } reverse(res.begin(), res.end()); }如图要返回的res需要手动传入。这时候可能有疑惑既然出了当前栈帧就会销毁那可以在堆上开辟空间new一个res吗绝对不可以调用者不知道返回的对象是堆上开辟的没有手动释放的话会引发内存泄漏2.5.2 右值引用和移动语义使用场景右值引用使用场景局部对象出了当前函数就销毁了不能传左值引用只能传右值引用。string s6 Solution().addStrings(11111, 22222); // 右值引用延长临时对象的生命周期,两个参数可以通过移动构造减少拷贝构造带来的消耗 cout s6.c_str() endl;移动构造和移动赋值// 移动构造 string(string s) { cout string(string s) -- 移动构造 endl; swap(s); } // 移动赋值 string operator(string s) { cout string operator(string s) -- 移动赋值 endl; swap(s); return *this; }两者都是通过swap交换将亡值的资源来实现构造大大减少了拷贝带来的消耗。rmove::string s5 move(s1); // 触发移动构造move之后移动构造导致s1的资源被释放 //cout s1.c_str() endl; error3. 类型分类1、C11以后进一步对类型进行了划分右值被分为纯右值(pure value简称prvalue)和将亡值(expiring value简称xvalue)。2、纯右值指的是那些字面量常量或求值结果相当于字面值或是一个不具名的临时对象。例如42、true、nullptr或者类似str.substr(1,2)、str1 str2传值返回函数调用或者整型a、baab等。3、将亡值指的是返回右值引用的函数的调用表达式和转换为右值引用的转换函数的表达式。例如move(x)、static_castX(x)4、泛左值(generalized value简称glvaue)包括将亡值和左值4. 引用折叠和完美转发4.1 引用折叠1、C中不能直接定义引用的引用但可以通过模板或者typedef中的类型操作可以构成引用的引用。int r i; // error,直接报错2、在构成引用的引用的时候C给出了一个引用折叠的规则右值引用的右值引用折叠成右值引用其他都折叠成左值引用。typedef int lref; typedef int rref; lref r1 n; // r1 的类型是 int lref r2 n; // r2 的类型是 int rref r3 n; // r3 的类型是 int rref r4 1; // r4 的类型是 int当然我们也可以通过模板来观察templateclass T void Function(T t) { int a 0; T x a; //x; cout a endl; cout x endl endl; } void test_04() { // 10是右值推导出T为int模板实例化为void Function(int t) Function(10); // 右值 int a; // a是左值推导出T为int引⽤折叠模板实例化为void Function(int t) Function(a); // 左值 // std::move(a)是右值推导出T为int模板实例化为void Function(int t) Function(std::move(a)); // 右值 const int b 8; // a是左值推导出T为const int引⽤折叠模板实例化为void Function(const int t) // 所以Function内部会编译报错x不能 Function(b); // const 左值 // std::move(b)右值推导出T为const int模板实例化为void Function(const int t) // 所以Function内部会编译报错x不能 Function(std::move(b)); // const 右值 }4.2 完美转发templateclass T class list { typedef list_nodeT Node; public: typedef list_iteratorT, T, T* iterator; typedef list_iteratorT, const T, const T* const_iterator; // 万能引用 templateclass X void push_back(X x) { insert(end(), forwardX(x)); } };如图完美转发forward可以保留x原本的类型。即如果没有forward若引用折叠之后X类型是右值引用x是某个右值的引用但是x本身(变量名)是左值直接传仍然为左值forward则可以保留x右值引用的属性。

相关新闻

C++实现WAV音频波形可视化:从文件解析到图形绘制完整指南

C++实现WAV音频波形可视化:从文件解析到图形绘制完整指南

1. 项目概述与核心价值最近在整理一些老旧的音频处理项目时,翻到了一个自己几年前写的C小工具,核心功能就是读取标准的WAV音频文件,然后把里面的声音数据画成波形图。这玩意儿虽然看起来简单,不就是读文件画图嘛,但真正…

2026/7/23 9:20:42 阅读更多 →
Swift 6新特性解析:并发安全与性能优化

Swift 6新特性解析:并发安全与性能优化

1. Swift 6 的版本演进与核心定位Swift 6 并非简单的增量更新,而是 Apple 在语言设计上一次战略性的集中突破。从版本演进路线来看,Swift 5.1 到 5.10 的每个重要里程碑都在为这次大版本更新铺路。2019 年的 Swift 5.1 引入模块稳定性,为 Swi…

2026/7/23 9:42:35 阅读更多 →
Python Pygame回合制卡牌对战游戏开发全流程解析

Python Pygame回合制卡牌对战游戏开发全流程解析

1. 项目概述与核心价值最近在社区里看到不少朋友对用Python做小游戏很感兴趣,尤其是卡牌对战这种既有策略性又有视觉反馈的类型。我自己也一直觉得,Pygame是Python入门游戏开发一个绝佳的跳板,它足够轻量,又能让你接触到游戏开发的…

2026/7/23 10:52:58 阅读更多 →

最新新闻

深入解析TI bq24765充电管理芯片:DPM、PCB布局与热设计实战

深入解析TI bq24765充电管理芯片:DPM、PCB布局与热设计实战

1. 项目概述:为什么我们需要关注充电管理芯片的“软实力”?在笔记本电脑、便携式工作站乃至各类高性能移动设备的研发中,电源系统设计往往是决定产品成败的“隐形战场”。一块优秀的电池充电管理芯片,其价值远不止于“把电充进去”…

2026/7/23 14:46:05 阅读更多 →
智能体总控平台架构设计与核心技术解析

智能体总控平台架构设计与核心技术解析

1. 智能体总控平台概述智能体总控平台作为新一代AI系统的中枢神经,正在重塑企业自动化与决策流程。这个平台本质上是一个能够协调、管理和监控多个AI智能体(Agent)协同工作的控制系统。想象一下交响乐团中的指挥家——总控平台就像那位指挥&a…

2026/7/23 14:46:05 阅读更多 →
BQ28Z610-R1电池管理芯片:高级充电算法与阻抗跟踪电量计量深度解析

BQ28Z610-R1电池管理芯片:高级充电算法与阻抗跟踪电量计量深度解析

1. BQ28Z610-R1:现代电池管理的“大脑”与“哨兵”如果你拆开过任何一款主流品牌的笔记本电脑、高端电动工具或者便携式医疗设备的电池包,有很大概率会发现一颗来自德州仪器(TI)的电池管理芯片。而在这些芯片中,BQ28Z6…

2026/7/23 14:46:05 阅读更多 →
MSPM33时钟系统实战:从PLL启动到低功耗切换的嵌入式开发指南

MSPM33时钟系统实战:从PLL启动到低功耗切换的嵌入式开发指南

1. 项目概述:为什么时钟系统是MCU的“心跳”与“节拍器”在嵌入式开发领域,尤其是面对MSPM33这类面向高性能与超低功耗双重挑战的微控制器时,时钟系统的配置往往是项目成败的第一个技术分水岭。你可以把它想象成整个芯片的“心跳”和“节拍器…

2026/7/23 14:46:05 阅读更多 →
怎么选专业的断桥铝系统门窗企业排行

怎么选专业的断桥铝系统门窗企业排行

家人们!今天来跟你们唠唠我老房换窗的事儿。我家这老房子啊,窗户那是老得不行了。一下雨,窗台边就渗水,窗台老是湿乎乎的,时间一长都发霉了。冬天的时候,窗户缝呼呼地漏风,屋里冷飕飕的。而且我…

2026/7/23 14:46:05 阅读更多 →
论文提交截止前24小时降AI工具使用手册:紧急降AI4.8元完整操作指南

论文提交截止前24小时降AI工具使用手册:紧急降AI4.8元完整操作指南

论文提交截止前24小时降AI工具使用手册:紧急降AI4.8元完整操作指南 系统整理了一下论文提交截止前降AI的完整方案,从工具选择到具体操作,每个阶段怎么用。 核心工具:嘎嘎降AI(www.aigcleaner.com)&#x…

2026/7/23 14:45:04 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 12:54:44 阅读更多 →

月新闻