C++进阶---C++11

news2025/1/11 2:17:28

本篇主要是介绍C++11中新添加的一些特性。


文章目录

  • 1.C++11简介
  • 2.列表初始化
  • 3.变量类型推导
  • 4.新增容器---静态数组array
  • 5.右值引用
  • 6.lambda表达式
  • 7.包装器
  • 8.新的类功能
  • 9.可变参数模板


一、C++11简介

  在2003 C++ 标准委员会曾经提交了一份技术勘误表 ( 简称 TC1) ,使得 C++03这个名字已经取代了
C++98称为 C++11 之前的最新 C++ 标准名称。不过由于 C++03(TC1) 主要是对 C++98标准中的漏洞
进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。
从C++0x C++11 C++ 标准 10 年磨一剑,第二个真正意义上的标准珊珊来迟。相比于
C++98/03, C++11 则带来了数量可观的变化,其中包含了约 140 个新特性,以及对 C++03标准中
约600 个缺陷的修正,这使得 C++11 更像是从 C++98/03 中孕育出的一种新语言。相比较而言,
C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更
强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,所以我们要作为一个
重点去学习。 C++11增加的语法特性非常篇幅非常多,我们这里没办法一 一讲解,所以本节课程
主要讲解实际中比较实用的语法。  
附加:c++参考文档: https://cplusplus.com/reference/

二、列表初始化

1.{}初始化

在C++98 中,标准允许使用花括号 {} 对数组或者结构体元素进行统一的列表初始值设定。
C++11扩大了用大括号括起的列表 ( 初始化列表 )的使用范围,使其可用于所有的内置类型和用户自
定义的类型, 使用初始化列表时,可添加等号(=),也可不添加。
如下程序可以反映出这个问题:
程序结果如下所示:

 

2.利用std::initializer_list

        采用auto来自动推导{}

程序结果如下:

 

std::initializer_list使用场景:
std::initializer_list一般是作为构造函数的参数,C++11对STL中的不少容器就增加
std::initializer_list作为参数的构造函数,这样初始化容器对象就更方便了。也可以作为operator=
的参数,这样就可以用大括号赋值
总结:C++11以后一切对象都可以用列表初始化。但是普通对象还是用以前的方式初始化,容器如果有需要可以用列表初始化。

三、变量类型推导

1.auto

在C++98中auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局
部的变量默认就是自动存储类型,所以auto就没什么价值了。C++11中废弃auto原来的用法,将
其用于实现自动类型腿断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初
始化值的类型。

 

 

2. decltype
关键字 decltype 将变量的类型声明为表达式指定的类型。

3.nullptr

由于 C++ NULL 被定义成字面量 0 ,这样就可能回带来一些问题,因为 0 既能指针常量,又能表示
整形常量。所以出于清晰和安全的角度考虑, C++11 中新增了 nullptr ,用于表示空指针。
#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif

 四、新增容器---静态数组array

五、右值引用和移动语义

1、左值引用和右值引用

左值:是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址+可以对它赋值,左值可以出现赋值符号的左边,右值不能出现在赋值符号的左边。定义时const修饰符后的左值,不能给他赋值,但是可以取它的地址。

左值引用:是左值的引用,相当于给左值起别名。

 

右值:是一个表示数据的表达式,如:字面常量、表达式的返回值,函数返回值(这个不能是左值引用返回)等等,右值可以出现在赋值符号的右边,但是不能出现在赋值符号的左边,右值不能取地址。

右值引用:是右值的引用,对右值取地址。

 

需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可
以取到该位置的地址,也就是说例如:不能取字面量 10 的地址,但是 rr1 引用后,可以对 rr1 取地
址,也可以修改 rr1 。如果不想 rr1 被修改,可以用 const int&& rr1 去引用,是不是感觉很神奇,
这个了解一下实际中右值引用的使用场景并不在于此,这个特性也不重要。

 

 2. 左值引用与右值引用比较

左值引用总结:
        1. 左值引用只能引用左值,不能引用右值。
        2. 但是 const 左值引用既可引用左值,也可引用右值。
右值引用总结:
        1. 右值引用只能右值,不能引用左值。
        2. 但是右值引用可以 move 以后的左值。

 

3.右值引用使用场景和意义

右值划分:内置类型:纯右值,自定义类型:将亡值。

1.左值引用的使用场景:
做参数和做返回值都可以提高效率。

 

左值引用的短板:
但是当函数返回对象是一个局部变量,出了函数作用域就不存在了,就不能使用左值引用返回,
只能传值返回。例如: bit::string to_string(int value) 函数中可以看到,这里只能使用传值返回,
传值返回会导致至少 1 次拷贝构造 ( 如果是一些旧一点的编译器可能是两次拷贝构造 )

 

 

 

 

 

右值引用和移动语义解决上述问题:
在bit::string 中增加移动构造,移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不
用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己。

 

 

4.STL容器插入接口函数也增加了右值引用版本:

 

 

 

 

5.完美转发

 

 std::forward 完美转发在传参的过程中保留对象原生类型属性

完美转发实际中的使用场景:

 

 

六.lambda表达式

  lambda表达式书写格式: [capture-list] (parameters) mutable -> return-type { statement
}
1. lambda表达式各部分说明
[capture-list] : 捕捉列表 ,该列表总是出现在 lambda 函数的开始位置, 编译器根据 []来
判断接下来的代码是否为lambda 函数 捕捉列表能够捕捉上下文中的变量供lambda
函数使用。
(parameters):参数列表。与 普通函数的参数列表一致 ,如果不需要参数传递,则可以
连同()一起省略.
mutable:默认情况下, lambda 函数总是一个 const 函数, mutable可以取消其常量
性。使用该修饰符时,参数列表不可省略( 即使参数为空 )。  
->returntype :返回值类型 。用 追踪返回类型形式声明函数的返回值类型 ,没有返回
值时此部分可省略。 返回值类型明确情况下,也可省略,由编译器对返回类型进行推
{statement} :函数体 。在该函数体内,除了可以使用其参数外,还可以使用所有捕获
到的变量。
注意:
lambda 函数定义中, 参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为
。因此 C++11 最简单的 lambda 函数为: []{} ; lambda 函数不能做任何事情。
  2. 捕获列表说明
捕捉列表描述了上下文中那些数据可以被lambda 使用 ,以及 使用的方式传值还是传引用
[var]:表示值传递方式捕捉变量var
  [=]:表示值传递方式捕获所有父作用域中的变量 ( 包括this)
[&var]:表示引用传递捕捉变量var
  [&]:表示引用传递捕捉所有父作用域中的变量 ( 包括this)
[this]:表示值传递方式捕捉当前的 this指针

 

 

注意:
a. 父作用域指包含 lambda函数的语句块
b. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。
  比如:[=, &a, &b] :以引用传递的方式捕捉变量 a b,值传递方式捕捉其他所有变量
[&, a, this] :值传递方式捕捉变量 a this,引用方式捕捉其他变量
c. 捕捉列表不允许变量重复传递,否则就会导致编译错误。  
比如:[=, a] = 已经以值传递方式捕捉了所有变量,捕捉 a重复.  
d. 在块作用域以外的 lambda 函数捕捉列表必须为空。
e. 在块作用域中的 lambda 函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者
非局部变量都会导致编译报错。
  f. lambda表达式之间不能相互赋值, 即使看起来类型相同 。

 函数对象与lambda表达式

 

 

 

在底层编译器对于 lambda 表达式的处理方式,完全就是按照函数对象的方式处理的,即:如
果定义了一个 lambda 表达式,编译器会自动生成一个类,在该类中重载了 operator()

七.包装器

function包装器
function 包装器 也叫作适配器。 C++ 中的 function 本质是一个类模板,也是一个包装器。

 

 

包装器可以很好的解决上面的问题
std::function 在头文件 < functional >
// 类模板原型如下
template < class T > function ;     // undefined
template < class Ret , class ... Args >
class function < Ret ( Args ...) > ;
模板参数说明:
Ret : 被调用函数的返回类型
Args… :被调用函数的形参

 

 

bind
std::bind 函数定义在头文件中, 是一个函数模板,它就像一个函数包装器 ( 适配器 ) 接受一个可
调用对象( callable object ),生成一个新的可调用对象来 适应 原对象的参数列表 。一般而
言,我们用它可以把一个原本接收 N 个参数的函数 fn ,通过绑定一些参数,返回一个接收 M 个( M
可以大于 N ,但这么做没什么意义)参数的新函数。同时,使用 std::bind 函数还可以实现参数顺
序调整等操作。
// 原型如下:
template < class Fn , class ... Args >
/* unspecified */ bind ( Fn && fn , Args && ... args );
// with return type (2)
template < class Ret , class Fn , class ... Args >
/* unspecified */ bind ( Fn && fn , Args && ... args );
可以将 bind 函数看作是一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对
象来 适应 原对象的参数列表。
调用 bind 的一般形式: auto newCallable = bind(callable,arg_list);
其中, newCallable 本身是一个可调用对象, arg_list 是一个逗号分隔的参数列表,对应给定的
callable 的参数。 当我们调用 newCallable 时, newCallable 会调用 callable, 并传给它 arg_list
的参数arg_list 中的参数可能包含形如 _n 的名字,其中 n 是一个整数,这些参数是 占位符 ,表示
newCallable 的参数,它们占据了传递给 newCallable 的参数的 位置 。数值 n 表示生成的可调用对
象中参数的位置: _1 newCallable 的第一个参数, _2 为第二个参数,以此类推。

 

八、新的类功能

默认成员函数
原来 C++ 类中,有 6 个默认成员函数:
1. 构造函数
2. 析构函数
3. 拷贝构造函数
4. 拷贝赋值重载
5. 取地址重载
6. const 取地址重载
最后重要的是前 4 个,后两个用处不大。默认成员函数就是我们不写编译器会生成一个默认的。
C++11 新增了两个:移动构造函数和移动赋值运算符重载。
针对移动构造函数和移动赋值运算符重载有一些需要注意的点如下:
如果你没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任
意一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类
型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,
如果实现了就调用移动构造,没有实现就调用拷贝构造。 如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中 的任意一个,那么编译器会自动生成一个默认移动赋值。默认生成的移动构造函数,对于内 置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋 值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。 ( 默认移动赋值跟上面移动构造 完全类似 ) 如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。
强制生成默认函数的关键字 default:
C++11 可以让你更好的控制要使用的默认函数。假设你要使用某个默认的函数,但是因为一些原
因这个函数没有默认生成。比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以
使用 default 关键字显示指定移动构造生成。
禁止生成默认函数的关键字delete:
如果能想要限制某些默认函数的生成,在C++98 中,是该函数设置成 private,并且只声明补丁
已,这样只要其他人想要调用就会报错。在C++11 中更简单,只需在该函数声明加上 =delete即
可,该语法指示编译器不生成对应函数的默认版本,称=delete 修饰的函数为删除函数。

九、可变参数模板

 

 

上面的参数 args 前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为 参数
,它里面包含了 0 N N>=0 )个模版参数。我们无法直接获取参数包 args 中的每个参数的,
只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特
点,也是最大的难点,即如何展开可变模版参数。由于语法不支持使用 args[i] 这样方式获取可变
参数,所以我们的用一些奇招来一一获取参数包的值。
STL 容器中的 empalce 相关接口函数:
template < class ... Args >
void emplace_back ( Args && ... args);

 

 

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

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

相关文章

Python高阶函数装饰器

“ 从CANoe vTESTstudio版本7开始&#xff0c;支持使用python编辑器编写python脚本。其中CANoe提供了许多API接口给python使用&#xff0c;大大扩展了python的可用性。在python中使用装饰器定义capl中的事件处理程序&#xff08;on key/on timer等&#xff09;。对此我们有必要…

C语言—宏定义

宏定义的作用是替换&#xff0c;再复杂也只能替换&#xff0c;不能用做计算&#xff1b; 一个源文件将另一个源文件的全部内容包含进来&#xff1b; 条件编译&#xff1b; 不带参数的宏定义&#xff1a; #include <stdio.h> #define PI 3.14int main() {printf("…

聊聊Redis消息队列-实现异步秒杀

一、前言 消息队列&#xff08;Message Queue&#xff09;, 字面意思就是存放消息的队列&#xff0c;最简单的消息队列模型包括3个角色&#xff1a; 消息队列&#xff1a;存储和管理消息&#xff0c;也被称为消息代理&#xff08;Message Broker&#xff09;;生产者&#xff…

Shell编程补充

Shell编程补充shell的变量定义变量的单双引号的不同输出变量父子shellshell子串BASHshell子串的用法shell统计变量长度输出程序运行时间结论:shell扩展变量用于处理变量值的创建子shell(进程列表)查看是否开启子shell在运行内置命令,外置命令shell编程总结shell的变量 定义变量…

小黑实习debug中遇到了函数式编程的混乱,特此进行的日常积累:python函数积累1

函数参数中有默认值&#xff0c;在函数内部会创建一块区域并维护这个默认值 # 在函数内存中会维护一块区域存储 [1,2,666,666,666] 100010001 def func(a1,a2[]):a2.append(666)print(a1,a2)func(100) func(1000)100 [666] 1000 [666, 666] def func(a1,a2[]):a2.append(666…

【nowcoder】笔试强训Day7

目录 一、选择题 二、编程题 2.1Fibonacci数列 2.2合法括号序列判断 一、选择题 1.JAVA属于&#xff08; &#xff09;。 A 操作系统 B 办公软件 C 数据库系统 D 计算机语言 计算机软件主要分为系统软件与应用软件两大类。系统软件主要包括操作系统、语言处理系统、数…

three.js之形状缓冲几何体

文章目录简介例子解释其他圆弧矩形专栏目录请点击 简介 Shape用来定义一个二维形状平面 官网常常与ShapeGeometry(形状缓冲几何体)搭配使用 官网&#xff0c;我们可以下运行下面的例子 例子 <!DOCTYPE html> <html lang"en"><head><meta cha…

玩转GPT--在线文本生成项目[可入坑~科普系列]

文章目录前言效果页面说明文字个数top_KTop_Ptemperature聊天上下文关联记忆项目部署获取项目获取模型运行彩蛋总结前言 没办法&#xff0c;最近ChatGPT杀疯了&#xff0c;没忍住&#xff0c;还是想look&#xff0c;look。没办法&#xff0c;哪个帅小伙能够忍受的了一个可以和…

数学知识---数论(质数和约数)

文章目录 1.质数1.1质数的判定---试除法1.2分解质因数---试除法1.3筛质数2.约数2.1试除法求约数2.2约数个数2.3约数之和2.4最大公约数---欧几里得算法(辗转相除法)1.质数 质数是针对所有大于1的自然数定义的,在大于1的整数中,如果只包含1和本身这两个约数,就被定义成为质…

【SpringCloud Alibaba】 初始化Sentinel

Sentinel 概念 特征 主要特征 开源生态​ 开启控制台 初始化工程 Sentinel 概念 分布式系统的流量防卫兵。随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点&#xff0c;从流量控制、流量路由、熔断降级、系统自适应过载保护…

Biotin-PEG-NH2,Biotin-PEG-amine,生物素-PEG-氨基材料改性用化学试剂

英文名称&#xff1a;Biotin-PEG-NH2&#xff0c;Biotin-PEG-amine 中文名称&#xff1a;生物素-聚乙二醇-氨基 Biotin-PEG-NH2是氨基化PEG中的一种&#xff0c;他可以用于材料改性&#xff1b;氨基和很多基团可以反应&#xff0c;如&#xff1a;羧基&#xff0c;活性酯&…

JavaScript:封装单向链表10种常见的操作方法

链表的优势 1.要存储多个元素的时候&#xff0c;除了数组还可以选择链表。 2.与之数组不同的是&#xff0c;链表中的元素在内存中不必是连续的空间。 3.链表中的每个元素由一个存储元素本身的节点和一个指向下一个节点的引用(指针或者连接)组成。 相比于数组&#xff0c;链表有…

QGIS基础:根据字段属性值或基于规则进行分类符号化显示

以下操作是对数据进行分类符号化&#xff0c;下面是原始操作数据&#xff1a; 基于分类符号化的字段是如下所示&#xff08;ZDTZM&#xff09;: A B C D 找到数据图层&#xff0c;右键属性&#xff0c;找到【符号化】&#xff0c;点击如下所示的分类&#xff1a; 在【valu…

mysql数据库完整实例-“汽车维修”

mysql数据库创建&#xff0c;编写&#xff0c;查询&#xff0c;自定义函数实战案例 创建汽车修理数据库&#xff0c;并完成数据库编写&#xff1a; 本文分三个部分&#xff0c;第一部分为数据库的创建编写和基础查询&#xff0c;第二部分为关联查询等复杂查询方法&#xff0c…

实验四:完整性实验

【实验目的】 掌握实体完整性、参照完整性和用户自定义完整性的定义的维护方法 【实验内容】 要实现这样一个功能&#xff1a;医生根据药品价表选择处方药品&#xff0c;录入数量和使用天数&#xff0c;系统根据医生选择的药品和录入的信息自动生成处方主表和处方明细表。功能…

Flink-按键分区状态-算子状态-广播状态

文章目录1. 按键分区状态&#xff08;Keyed State&#xff09;1.2基本概念和特点1.3 支持的结构类型1.4 代码实现1.5 状态生存时间&#xff08;TTL&#xff09;2 算子状态&#xff08;Operator State&#xff09;2.1 基本概念和特点2.2 状态类型2.3 代码实现3. 广播状态&#x…

2022年安徽建筑施工塔式起重机(建筑特种作业)模拟题库及答案

百分百题库提供特种工&#xff08;塔式起重机&#xff09;考试试题、特种工&#xff08;塔式起重机&#xff09;考试真题、特种工&#xff08;塔式起重机&#xff09;证考试题库等,提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 87.塔式起重机滑轮上…

基于历史对比学习的时序知识图谱推理

时序知识图谱 知识图谱&#xff08;KGs&#xff09;作为人类知识的集合&#xff0c;在自然语言处理、推荐系统和信息检索等领域显示展现了很好的前景。传统的KG通常是一个静态知识库&#xff0c;它使用图结构数据拓扑&#xff0c;并以三元组&#xff08;s, p, o&#xff09;的…

自定义ContentProvider案例

自定义ContentProvider案例 1.条件准备 app5往外暴漏数据app7接收和操作远程数据图1 app5目录结构 图2 app7目录结构 2.参考代码 完整代码&#xff1a; https://download.csdn.net/download/weixin_41957626/87346497 1)app5的代码 &#xff08;1&#xff09;app5的entity&…

C#项目实战——【实例】企业人事管理系统(一):1、系统分析;2、系统设计;3、系统运行环境;

学习《C#从入门到精通》&#xff0c;边学边练记录实现过程。 1、系统分析 1.1、需求分析 基于其他企业人事管理软件的不足&#xff0c;要求能够制作一个可以方便、快捷地对职工信息进行添加、修改、删除的操作&#xff0c;并且可以在数据库中存储相应职工的照片。为了能够更…