【C++学习篇】C++11

news/2025/2/11 3:12:41/

目录

​编辑

1. 初始化列表{}

1.1 C++98中的{}

 1.2 C++11中的{} 

2.  C++11中的std::initializer_list

3. 右值引用和移动语义 

3.1 左值和右值

3.2 左值引用和右值引用 

3.3 引用延长生命周期 

3.4 左值和右值的参数匹配

3.5 右值引⽤和移动语义的使⽤场景

3.5.1 左值引⽤主要使⽤场景回顾

3.5.2  移动构造和移动赋值

3.6 类型分类

3.7 引用折叠

3.8 完美转发


1. 初始化列表{}

1.1 C++98中的{}

C++98中⼀般数组和结构体可以⽤{}进⾏初始化。

 1.2 C++11中的{} 

C++11以后想统⼀初始化⽅式,试图实现⼀切对象皆可⽤{}初始化,{}初始化也叫做列表初始化。

1. 内置类型⽀持,⾃定义类型也⽀持,⾃定义类型本质是类型转换,中间会产⽣临时对象,最后优化了以后变成直接构造。

2. {}初始化的过程中,可以省略掉=

C++11列表初始化的本意是想实现⼀个⼤统⼀的初始化⽅式,其次他在有些场景下带来的不少便利,如容器push/inset多参数构造的对象时,{}初始化会很⽅便。

示例:

 

2.  C++11中的std::initializer_list

上⾯的初始化已经很⽅便,但是对象容器初始化还是不太⽅便,⽐如⼀个vector对象,我想⽤N个值去构造初始化,那么我们得实现很多个构造函数才能⽀持,例如实现这个功能:

vector<int> v1={1,2,3};

vector<int> v2={1,2,3,4,5};//其实std::initializer_list的功能有点像C语言的int n1[]={1,2,3}

1. C++11库中提出了⼀个std::initializer_list的类, auto il = { 10, 20, 30 }; // the type of il is an initializer_list ,这个类的本质是底层开⼀个数组,将数据拷⻉过来,std::initializer_list内部有两个指针分别指向数组的开始和结束.

 2. 容器⽀持⼀个std::initializer_list的构造函数,也就⽀持任意多个值构成的 {x1,x2,x3...} 进⾏初始化。STL中的容器⽀持任意多个值构成的 {x1,x2,x3...} 进⾏初始化,就是通过std::initializer_list的构造函数⽀持.

initializer_list官方链接https://legacy.cplusplus.com/reference/initializer_list/initializer_list/https://legacy.cplusplus.com/reference/initializer_list/initializer_list/https://legacy.cplusplus.com/reference/initializer_list/initializer_list/

3. 右值引用和移动语义 

C++98的C++语法中就有引⽤的语法,⽽C++11中新增了的右值引⽤语法特性,C++11之后我们之前学习的引⽤就叫做左值引⽤。⽆论左值引⽤还是右值引⽤,都是给对象取别名。 

3.1 左值和右值

1. 左值 是⼀个表⽰数据的表达式(如变量名或解引⽤的指针),⼀般是有持久状态存储在内存中,我们可以获取它的地址,左值可以出现赋值符号的左边,也可以出现在赋值符号右边。定义时const
修饰符后的左值,不能给他赋值,但是可以取它的地址。 

常见的左值:传引用返回的值,我们定义的变量,可以取地址的值。

2. 右值 也是⼀个表⽰数据的表达式,要么是字⾯值常量、要么是表达式求值过程中创建的临时对象等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址。 

 常见的右值:临时变量,匿名对象,传值返回,自变量常量,不可以取址的。

3. 值得⼀提的是,左值的英⽂简写为lvalue,右值的英⽂简写为rvalue。传统认为它们分别是left value、right value 的缩写。现代C++中,lvalue 被解释为loactor value的缩写,可意为存储在内
存中、有明确存储地址可以取地址的对象,⽽ rvalue 被解释为 read value,指的是那些可以提供数据值,
但是不可以寻址,例如:临时变量,字⾯量常量,存储于寄存器中的变量等,也就是说左值和右值的核⼼区别就是能否取地址。

3.2 左值引用和右值引用 

 1. Type& r1 = x; Type&& rr1 = y;第⼀个语句就是左值引⽤,左值引⽤就是给左值取别名,第⼆个就是右值引⽤,同样的道理,右值引⽤就是给右值取别名。

2. 左值引⽤不能直接引⽤右值,但是const左值引⽤可以引⽤右值。(因为右值具有常性,左值直接引用右值会权限放大,所以要用const)

 

3. 右值引⽤不能直接引⽤左值,但是右值引⽤可以引⽤move(左值)。(move相当于强转)

4. move是库⾥⾯的⼀个函数模板,本质内部是进⾏强制类型转换,当然他还涉及⼀些引⽤折叠的知识,这个我们后⾯会细讲。

5. 需要注意的是变量表达式都是左值属性,也就意味着⼀个右值被右值引⽤绑定后,右值引⽤变量变量表达式的属性是左值。

6. 语法层⾯看,左值引⽤和右值引⽤都是取别名,不开空间。从汇编底层的⻆度看下⾯代码中r1和rr1汇编层实现,底层都是⽤指针实现的,没什么区别。底层汇编等实现和上层语法表达的意义有时是背离的,所以不要然到⼀起去理解,互相佐证,这样反⽽是陷⼊迷途。

3.3 引用延长生命周期 

 右值引⽤可⽤于为临时对象延⻓⽣命周期,const 的左值引⽤也能延⻓临时对象⽣存期,但这些对象⽆法被修改。

 

3.4 左值和右值的参数匹配

 1. C++98中,我们实现⼀个const左值引⽤作为参数的函数,那么实参传递左值和右值都可以匹配。

2. C++11以后,分别重载左值引⽤、const左值引⽤、右值引⽤作为形参的f函数,那么实参是左值会匹配f(左值引⽤),实参是const左值会匹配f(const 左值引⽤),实参是右值会匹配f(右值引⽤)。

3. 右值引⽤变量在⽤于表达式时属性是左值。

3.5 右值引⽤和移动语义的使⽤场景

3.5.1 左值引⽤主要使⽤场景回顾

左值引⽤主要使⽤场景是在函数中左值引⽤传参和左值引⽤传返回值时减少拷⻉,同时还可以修改实参和修改返回对象的价值。左值引⽤已经解决⼤多数场景的拷⻉效率问题,但是有些场景不能使⽤传左值引⽤返回,如addStrings和generate函数,C++98中的解决⽅案只能是被迫使⽤输出型参数解决。那么C++11以后这⾥可以使⽤右值引⽤做返回值解决吗?显然是不可能的,因为这⾥的本质是返回对象是⼀个局部对象,函数结束这个对象就析构销毁了,右值引⽤返回也⽆法概念对象已经析构销毁的事实。 

3.5.2  移动构造和移动赋值

1. 移动构造函数是⼀种构造函数,类似拷⻉构造函数,移动构造函数要求第⼀个参数是该类类型的引⽤,但是不同的是要求这个参数是右值引⽤,如果还有其他参数,额外的参数必须有缺省值。

2. 移动赋值是⼀个赋值运算符的重载,他跟拷⻉赋值构成函数重载,类似拷⻉赋值函数,移动赋值函数要求第⼀个参数是该类类型的引⽤,但是不同的是要求这个参数是右值引⽤。 

3. 对于像string/vector这样的深拷⻉的类或者包含深拷⻉的成员变量的类,移动构造和移动赋值才有意义,因为移动构造和移动赋值的第⼀个参数都是右值引⽤的类型,他的本质是要“窃取”引⽤的
右值对象的资源,(就是资源转移)
⽽不是像拷⻉构造和拷⻉赋值那样去拷⻉资源,从提⾼效率。下⾯的bit::string样例实现了移动构造和移动赋值,我们需要结合场景理解。 

string ret = string("ssss");先构造临时对象str,然后移动构造到ret。(相当于ret把他的空跟str里内容进行交换swap了)

3.6 类型分类

 C++11以后,进⼀步对类型进⾏了划分,右值被划分纯右值(pure value,简称prvalue)和将亡值
expiring value,简称xvalue)。

3.7 引用折叠

1. C++中不能直接定义引⽤的引⽤如 int& &&ret=i,这样写会直接报错,通过模板或 typedef中的类型操作可以构成引⽤的引⽤。

2. 通过模板或 typedef 中的类型操作可以构成引⽤的引⽤时,这时C++11给出了⼀个引⽤折叠的规则:右值引⽤的右值引⽤折叠成右值引⽤,所有其他组合均折叠成左值引⽤。

3.8 完美转发


http://www.ppmy.cn/news/1571035.html

相关文章

npm无法加载文件 因为此系统禁止运行脚本

安装nodejs后遇到问题&#xff1a; 在项目里【node -v】可以打印出来&#xff0c;【npm -v】打印不出来&#xff0c;显示npm无法加载文件 因为此系统禁止运行脚本。 但是在winr&#xff0c;cmd里【node -v】,【npm -v】都也可打印出来。 解决方法&#xff1a; cmd里可以打印出…

如何在RTACAR中配置IP多播(IP Multicast)

一、什么是IP多播 IP多播&#xff08;IP Multicast&#xff09;是一种允许数据包从单一源地址发送到多个目标地址的技术&#xff0c;是一种高效的数据传输方式。 多播地址是专门用于多播通信的IP地址&#xff0c;范围从 224.0.0.0到239.255.255.255 与单播IP地址不同&#x…

基础入门-网站协议身份鉴权OAuth2安全Token令牌JWT值Authirization标头

知识点&#xff1a; 1、网站协议-http/https安全差异&#xff08;抓包&#xff09; 2、身份鉴权-HTTP头&OAuth2&JWT&Token 一、演示案例-网站协议-http&https-安全测试差异性 1、加密方式 HTTP&#xff1a;使用明文传输&#xff0c;数据在传输过程中可以被…

MySQL 的理解

1. MySQL 概述 MySQL 是一种广泛使用的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;。它由瑞典 MySQL AB 公司开发&#xff0c;后被甲骨文&#xff08;Oracle&#xff09;公司收购。凭借高性能、可靠性、易用性和开放性等诸多优势&#xff0c;MySQL 在 Web 应用开发…

代码随想录day06

242.有效的字母异位词 刚学哈希表想着使用unordered_set来实现&#xff0c;结果无法通过&#xff0c;原因是对字母异位词理解有问题&#xff0c;字母异位词是通过重新排列不同单词或短语的字母而形成的单词或短语&#xff0c;并使用所有原字母一次。对字母出现的次数有要求&am…

202412 青少年软件编程等级考试C/C++ 二级真题答案及解析

第 1 题 逆行 题目描述 网上有个段子说&#xff1a;妻子在家听广播&#xff0c;听到某高速路上有一辆车在逆行&#xff0c;想到丈夫在那条高速上行驶&#xff0c;就打电话对丈夫说&#xff1a;“老公啊&#xff0c;你走的那条高速上有一辆车在逆行&#xff0c;你小心点。”她丈…

【C++】多态详细讲解

本篇来聊聊C面向对象的第三大特性-多态。 1.多态的概念 多态通俗来说就是多种形态。多态分为编译时多态(静态多态)和运⾏时多态(动态多态)。 编译时多态&#xff1a;主要就是我们前⾯讲的函数重载和函数模板&#xff0c;他们传不同类型的参数就可以调⽤不同的函数&#xff0c;通…

CST的TLM算法仿真5G毫米波阵列天线及手机

直奔主题&#xff0c;2022版本的5G毫米波流程更简单、仿真更快、占用硬盘和内存更少、功能更多。 第一部分&#xff0c;毫米波天线阵列 自带案例库中的毫米波天线阵列&#xff0c;这个很多毫米波用户都不陌生。2022版本中&#xff0c;该案例进行了微调和优化&#xff0c;用户可…