C++11新特性(上)----《Hello C++ Wrold!》(25)--(C/C++)

C++11新特性(上)----《Hello C++ Wrold!》(25)--(C/C++)

文章目录

前言

C++ 作为一门经典且持续演进的编程语言,其标准迭代始终围绕 “提升开发效率、优化性能、完善语言特性” 展开。1998 年首个国际标准 C++98 奠定了语言基础,而 2011 年发布的 C++11 标准则堪称一次里程碑式的更新 —— 它不仅修复了早期版本的诸多缺陷,更引入了大量革命性特性,从根本上改变了 C++ 的编程范式,为开发者提供了更简洁、高效且安全的编码工具。

本文将聚焦 C++11 标准的核心新增特性,从 “统一列表初始化” 的语法简化、“auto/decltype/nullptr” 的声明优化,到 STL 容器与接口的扩展,再到 “右值引用、移动语义、完美转发” 等深刻影响性能的底层机制,以及类功能的增强(如默认移动构造、final/override 关键字),系统梳理这些特性的设计逻辑与实际应用场景。

无论是初学时对 C++11 语法的困惑,还是开发中对 “为何优先用 emplace_back 而非 push_back”“move 与 forward 该如何正确使用” 等问题的疑问,都能通过本文的拆解得到解答。文中将结合具体代码示例,区分易混淆概念(如 initializer_list 与多参数构造隐式转换、左值 / 右值与左值引用 / 右值引用),同时兼顾 “实用性” 与 “原理性”—— 既说明特性的日常用法,也点明编译器层面的特殊处理,帮助读者不仅 “会用”,更能 “理解为什么这么用”,为后续深入 C++ 高阶开发或迁移至更高版本(如 C++14/C++17)打下坚实基础。

历史知识

C++ 编程语言的第一个国际标准是1998年发布的–C++98
下面的话讲的是C++11引入的特性

除了这些,还有范围for 智能指针这些

统一的列表初始化

C++11扩大了用大括号括起的列表的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用列表初始化时,可添加等号(=),也可不添加。

–C++11中列表初始化也可以适用于new表达式中
这个的话日常不推荐用,但是要能看得懂
比如:int y ={2};int y{2};structPoint{Point(int x,int y):_x(x),_y(y){}int _x;int _y;}; Point p1 ={1,1}; Point p1{1,1}--本来应该是Point p1(1,1); 前面这两个其实也是调用的Point的构造函数,其实是C++11支持了多参数构造函数的隐式类型转换 --如果想这两个行不通,就在构造函数前加个explicit Point* ptr3 =new Point[2]{{0,0},{1,1}};const Point& r ={3,3};--这个const去不得,因为创建一个Point临时对象(常性)

initializer_list

这是一个类型
auto 用于初始化列表 {...} 时,编译器会优先推导出 std::initializer_list<T>类型
一般容器的构造函数和赋值=都支持这个类型进行
vector<int> v1 ={1,2,3,4,3};// 调用initializer_list的vector构造函数 Point p1 ={1,1};// 多参数构造函数的隐式类型转换 这俩个要区分--不是一个规则哈 注意: 上面的{1,2,3,4,3}转换成initializer_list类型时: 其实是编译器会在常量区自动创建一个隐藏的常量数组 initializer_list 只是用指针引用这个数组,而不是自己存储数据。 --这个类型自己模拟实现不太行,库里面的这个类型编译器会做特殊照护 

声明

多了autonullptrdecltype
nullptr和NULL的区别 NULL有时直接被定义成00既能表示指针常量,又能表示整形常量 #defineNULL((void*)0) #define NULL0nullptr是空指针 引申:宏不常用的,基本上用 constenuminline去代替宏 
decltype:关键字decltype可以将变量的类型声明为表达式指定的类型 decltype推出对象的类型,再定义变量,或者作为模板实参 其实也就是eg:decltype(pf)看成一个类型去用 跟auto的区别:auto不能eg:auto x;这样不带初始化 eg:int pf =0;int a =0;double b =1.0;decltype(a*b) c =2;decltype(pf) pf2; B<decltype(pf)> bb1;//B是类 引申:函数能通过函数指针调用 eg:auto x = malloc; 之后x和malloc的用法和作用就相同了 

STL里面的一些变化

新容器

增加了arrayforward_listunordered_mapunordered_set

但是array -- 数组forward_list -- 单链表没啥用

关于数组的话:一般也用vector代替,因为原生数组容易越界之后检查不出来

新接口

对于const迭代器,给他添加了cbegincendcrbegincrend,但是这几个接口没啥用,没必要
所有的容器的构造函数都支持了initializer_list那种方式的初始化

所有的容器都支持了移动构造和移动赋值

大多数容器的很多接口都多了emplace系列的–比如以前是back 现在多了个emplace_back–并且本来的接口有些也支持了右值引用的方式

新的类功能

新增加了移动构造函数和移动赋值运算符重载

如果你没有自己实现移动构造,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个,编译器会自动生成一个默认移动构造–对内置类型会浅拷贝,对自定义类型如果有移动构造就用移动构造,没有就用拷贝构造

如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个,编译器会自动生成一个默认移动赋值–对内置类型会浅拷贝,对自定义类型如果有移动赋值就用移动赋值,没有就用拷贝赋值
允许在类定义时给成员变量初始缺省值

finaloverride
强制生成默认函数的关键字default eg:Person(Person&& p) = default;

禁止生成默认函数的关键字delete eg:Person(Person&& p) = delete;

左值引用和右值引用

左值引用是以前本来就支持的哈,右值引用还是C++11引入的

左值和右值

可以取地址的叫做左值 左值一般是可以被修改的

不能取地址的叫做右值(右值是不允许被修改的)
内置类型的右值叫做纯右值

自定义类型的右值叫做将亡值

左值引用和右值引用

左值引用就是eg: int & a = b; 粗略: 给左值取别名(b是 int b =0;)

右值引用是eg: double && r = x+y; 粗略: 给右值取别名(x y本来是double x = 1.1,y = 2.0)

注意:右值引用之后其实是让他拥有了左值的属性(有地址,并且可以被修改)
问题:

左值引用可以给右值取别名吗–const的左值引用可以eg: const int a = .....

右值引用可以给左值取别名吗-- move以后的左值可以eg: int && c = move(b);
关于这个move:拿上面举例:
voidfunc(constint& r){}voidfunc(int&& r){} 也构成函数重载哈,编译器会选择最匹配的去用 eg:传的是右值,用第二个 传的是左值,用第一个 
左值引用的核心价值就是减少拷贝,提高效率

右值引用的核心价值是进一步减少拷贝,弥补左值引用没有解决的场景,比如:传值返回

场景举例:1.自定义类型中深拷贝的类,必须传值返回时(类大的时候用,小用不用区别不大)

2.容器的插入接口,如果插入对象是右值,可以用移动构造转移资源给数据结构中的对象,也可以进一步减少拷贝

注意:浅拷贝的类只能直接拷贝,移动拷贝是不行的–因为给也给的是指针

移动构造

这个的话在出现将亡值赋值的时候会出现

这个的话就相当于把将亡值的东西给那个被赋值的,被赋值的把之前的东西给将亡值(将亡值之前存储东西的地方直接给被赋值的人了–有点像吸收别人的功力那种意思)

–只是资源被转移了哈,原来的对象还在那,不算是空对象

纯右值也会的哈,只是没啥必要而已,除非eg:vector<int>那种数组很大的
string func()//不能搞成string&或者string&&哈{ string str("xxxx");return str;} main函数里面 string s =func();--这里的话会str先深拷贝给func(),再func()移动拷贝给s --编译器优化后只有一次移动拷贝了 但是编译器会进行优化:1.连续的构造或者拷贝构造,合二为一 2.开绿灯行为:eg:这里的str直接被当成将亡值给了s eg: list<string>lt; lt.push_back("22222"); 此时也是一次移动拷贝,因为"22222"隐式转换成string的时候生成了个匿名对象(C++11的认知)--如果用的是自己模拟实现的那种string的话,生成匿名对象时还会有一次拷贝构造(现代写法)--有移动定义也是这样 
移动语义:就是用右值引用实现移动构造和移动赋值

完美转发

万能引用

万能引用的作用:既可以接收左值,又可以接受右值

实参如果是左值的话,他就是左值引用–此时是引用折叠

实参如果是右值的话,他就是右值引用

完美转发

在这里插入图片描述
补充:上面的Fun是 voidFun(int& x){}----1voidFun(constint& x){}----2voidFun(int&& x){}---3voidFun(constint&& x){}----4 调用:PerfectForward(std::move(a));PerfectForward(std::move(b)); 这俩个的话其实最后一个是用的1,一个用的2 因为Fun(t)传的时候t是右值引用--所以是左值的属性 --没用右值属性的话,在移动定义时,无法完成资源转移!!! 此时如果想保留右值引用是右值的属性的话,就要用到完美转发了 完美转发就是加个:forward<T> 也就是template<typenameT>voidPerfectForward(T&& t){Fun(forward<T>(t));}
要注意的是:如果想一直保持原来的属性,在每次传参的时候都要使用完美转发

–中间少用了一次就会永远丢失原本的属性

Read more

【MySQL】第八节—表的增删改查,吃透这篇就够了(下)

【MySQL】第八节—表的增删改查,吃透这篇就够了(下)

Hi,我是云边有个稻草人-ZEEKLOG博客个人主页,今天结束表的增删改查,继续! 《MySQL》本篇文章所属专栏—持续更新中!   目录 三、Update 3.1【将孙悟空同学的数学成绩变更为 80 分】 3.2【将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分】 3.3【将总成绩倒数前三的 3 位同学的数学成绩加上 30 分】 3.4【将所有同学的语文成绩更新为原来的 2 倍】 四、Delete 4.1 删除数据 【删除孙悟空同学的考试成绩】 【删除总分倒数第一的同学信息】 【删除整张表数据】 4.2 截断表 五、去重数据表,插入查询结果 六、

By Ne0inhk
【Spring MVC】一篇文章带你吃透 SpringMVC 请求

【Spring MVC】一篇文章带你吃透 SpringMVC 请求

🎬 那我掉的头发算什么:个人主页 🔥 个人专栏: 《javaSE》《数据结构》《数据库》《javaEE》 ⛺️待到苦尽甘来日 引言 上回说到,SpringMVC主要涉及三个方面——建立连接、请求、响应。建立连接的部分我们已经了解了,创建请求的工具我们也介绍了。下面,我们将详细的去学习请求与响应的具体实现! 文章目录 * 引言 * 请求 * 传递单个参数 * 传递多个参数 * 传递对象 * 后端参数重命名(后端参数映射) * 传递数组 * 传递集合 * 传递JSON * 获取url中的参数@PathVariable * 上传文件@RequestPart * 获取Cookie/Session * 获取Header 请求 访问不同的路径, 就是发送不同的请求. 在发送请求时, 可能会带⼀些参数, 所以学习Spring的请求, 主要是学习如何传递参数到后端以及后端如何接收。 传递单个参数 简单的参数传递上一节已经提到过了,诸如下面的代码,运行之后,在url中传递keyword的值,就可

By Ne0inhk
Flutter 组件 dart_dev 适配鸿蒙 HarmonyOS 实战:效能基座方案,构建全生命周期自动化开发流水线与研发套件治理架构

Flutter 组件 dart_dev 适配鸿蒙 HarmonyOS 实战:效能基座方案,构建全生命周期自动化开发流水线与研发套件治理架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 dart_dev 适配鸿蒙 HarmonyOS 实战:效能基座方案,构建全生命周期自动化开发流水线与研发套件治理架构 前言 在鸿蒙(OpenHarmony)生态迈向大规模工业化协同、涉及海量跨端功能并发验证及严苛代码交付质量标准的背景下,如何实现研发流程的“机器化”约束,已成为决定团队产出稳定性与效能上限的关键。在鸿蒙设备这类强调 AOT 极致性能与多包(HAP/HSP)协同部署的环境下,如果研发环节依然依赖分散的散装脚本或非标的 Git 工作流,由于由于环境配置的微差异,极易由于由于“本地通过,远端爆炸”导致集成交付效率的高频损耗。 我们需要一种能够统一任务调度(Task Runner)、支持全量规范校验且具备“一站式”研发脚本治理能力的基座方案。 dart_dev 为 Flutter 开发者引入了“研发即代码(Dev-as-Code)

By Ne0inhk
RabbitMQ如何成为分布式系统的“神经中枢“?——从安装部署到C++调用实战的完整流程,带你体验它的奥妙所在!​

RabbitMQ如何成为分布式系统的“神经中枢“?——从安装部署到C++调用实战的完整流程,带你体验它的奥妙所在!​

文章目录 * 本篇摘要 * ①·RabbitMq(轻量级消息队列中间件) 介绍 * RabbitMQ 是什么? * 核心功能与特点 * 1. **核心功能** * 2. **核心优势** * RabbitMQ 的核心概念 * 1. **生产者(Producer)** * 2. **消费者(Consumer)** * 3. **队列(Queue)** * 4. **交换机(Exchange)** * 5. **绑定(Binding)** * 工作流程(以 Direct 交换机为例) * 常见应用场景 * RabbitMQ 与相关技术对比 * 图像理解 * 总结一句话 * ②·RabbitMq 安装教程 * RabbitMq安装 * **1. 安装 RabbitMQ** * **2. 启动 & 检查状态** * **3. 创建管理员用户(

By Ne0inhk