当前位置: 首页 > news >正文

C++——C++11 第一篇

目录

 统一的列表初始化

 {}初始化

decltype 

​编辑 nullptr

STL中一些变化

 右值引用和移动语义

 左值引用和右值引用

 总结

左值引用优缺点 

右值引用(将亡值) 

 拷贝赋值和移动赋值

万能引用|完美转发

移动构造和移动赋值注意事项 

delete


 

点击跳转了解C++11

 统一的列表初始化

 {}初始化

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

 

std::initializer_list使用场景:
std::initializer_list一般是作为构造函数的参数,C++11对STL中的不少容器就增加
std::initializer_list作为参数的构造函数,这样初始化容器对象就更方便了。也可以作为operator=
的参数,这样就可以用大括号赋值

把大括号里面的东西给对象,对象就会被认为是initializer_list类型

点击跳转了解

 所有的容器都支持了这样的构造函数,所以我们可以用列表初始化。

调用支持list(initializer_list<value_type>il)类似这样的构造函数

我们自己写的vectoru不支持这种写法 ,因为我们没initializer_list,我们在之前写的vector中这样写,就可以实现C++11这种写法

 有了上面的initializer_list,我们还可以这样写

 v4是隐式类型转换,而且调用了构造函数

map也可以这样写,首先是map支持 initializer_list的构造,而每个数据都是pair,pair支持初始化,调用了pair的构造。

 C++11以后一切对象都可以用列表初始化,但是普通对象最好用以前的方式初始化,容器之类的可以用列表初始化

decltype 

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

y1的类型是由x类型决定,y2的类型由等号右边的值决定,auto和decltype有差异,俩者不一样。 

 nullptr

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

STL中一些变化

 新容器
用橘色圈起来是C++11中的一些几个新容器,但是实际最有用的是unordered_map和
unordered_set。这两个我们前面已经进行了非常详细的讲解,其他的大家了解一下即可。

 

 容器中的一些新方法

都支持initializer_list构造,用来支持列表初始化。
如果我们再细细去看会发现基本每个容器中都增加了一些C++11的方法,但是其实很多都是用得
比较少的。
比如提供了cbegin和cend方法返回const迭代器等等,但是实际意义不大,因为begin和end也是
可以返回const迭代器的,这些都是属于锦上添花的操作。

 array对越界很敏感。实际情况arrar用的很少,因为C语言使用关了。

 右值引用和移动语义

 左值引用和右值引用

 什么是左值?什么是左值引用?

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

 

 什么是右值?什么是右值引用?

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

 右值不能取地址

 

 左值引用不能去引用右值,加上const就可以

 

所以在函数传参的时候我们如果使用了引用传参,就加const,这样该函数既能接收左值,又能接收右值,若不加const只能加收左值引用,不能引用右值

 右值引用不能直接引用左值,对左值加上move函数,右值引用就可以引用左值了

 此时不报错

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

 这里rr1和rr2都是左值,因为他们可以进行取地址

 总结

 左值引用总结:

我们可以获取它的地址+可以对它赋值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边。

 1. 左值引用只能引用左值,不能引用右值。
2. 但是const左值引用既可引用左值,也可引用右值

右值引用总结:

右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能
取地址。
1. 右值引用只能右值,不能引用左值。
2. 但是右值引用可以move以后的左值。

左值引用优缺点 

左值引用解决哪些问题:

1.做参数

a.减少拷贝,提高效率   b.做输出型参数

2.做返回值

a.减少拷贝,提高效率  b.引用返回,可以修改返回对象(比如:operator[]). 

缺点:

以to_string为例 ,它是传值返回,简单实现to_string,返回的str是局部对象,出了作用域就会销毁,不能用左值引用返回,如果用左值引用返回此时程序就崩了,因为str已经析构了。

 还有这道杨辉三角的返回值,返回的是vector<vector<int>>,C++98左值引用面对这种场景很难处理

 我们可以这样修改,这种优化的缺点不太符合使用习惯

右值引用(将亡值) 

 C++11的右值引用就能解决上面的问题

这里有俩次string的拷贝构造,编译器优化后只有一次拷贝构造,这里出了作用域str就销毁,所以不能用左值引用返回,我们可以用右值返回

namespace myspace
{myspace::string to_string(int value){myspace::string str;//return str;}
}
int main()
{myspace::string ret = to_string(-3456);return 0;
}

 右值引用的提出,产生了移动构造

拷贝构造是左值引用,移动构造是右值引用,右值引用也可以走拷贝构造因为被const所修饰,C++每次在选择函数时,会选择最匹配的函数进行使用,既有左值引用又有右值引用,当使用右值引用时,就会走右值引用

 右值:1.内置类型右值——纯右值(如x+y)  2.自定义类型右值——将亡值(声明周期一般只在那一行或函数结束)

这里s是将亡值,用swap保留s的资源。所以叫移动构造

 

 str1的资源被转移,move(str1)这里吧str1转成了右值,str1就是将亡值,str1的资源就被转移了

 这里之前是一次拷贝构造,现在是一次移动构造,选择最匹配的函数,拷贝构造的代价要大于移动构造的代价,因为拷贝了临时对象之后,还要释放临时对象,移动构造是直接转移资源,不需要拷贝。

 

注释掉移动构造变成了拷贝构造

 左边是拷贝构造(此时没有写移动构造),右边是写了移动构造之后,编译器匹配到了移动构造

 拷贝赋值和移动赋值

 屏蔽掉移动构造之后运行程序。

 

 取消移动构造的注释,加上移动赋值,把s和将亡值进行交换,将亡值在被销毁的时候,会带着之前s的值一并被销毁

 

 右值引用增加了移动构造和移动赋值之后,提高了效率,减少了资源的拷贝和释放,直接把资源进行交换。

 右值引用在延长对象的生命周期,这种说法是错的,因为他转移了资源,并没有延长对象的生命周期

 

 

 这里s1+s2是一个表达式,表达式的值是一个临时值,临时对象是右值(将亡值)

C++11以后提供了移动构造和移动赋值

 STL中所有的插入接口,都有右值引用,解决了用传值返回类型对象的拷贝问题

 这里传匿名对象(匿名对象周期只在那一行),传的是右值(将亡值),这里转移俩次是跟内部实现有关系,这个不需要关注,在这里只需搞清楚移动构造即可

 

万能引用|完美转发

 如果普通参数是这样则成为右值版本,但是在模板里这样使用就会被称作万能引用,引用折叠。

折叠的规则很复杂,简单来说就是右值,左值都能传过去,即T既能引用左值,又能引用右值

模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。
// 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力,
// 但是引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左值,
引用折叠以后,统统变成了左值

完美转发: std::forward<T>(t)在传参的过程中保持了t的原生类型属性。

 

 完美转发引用场景

应用在以前写的链表的push_back

main函数 

 

理论而言第一个push_back走左值版本,第二个走右值版本,但是这里都是拷贝构造

 

 这是因为万能引用进行了折叠,这是语法特性,我们进行完美转发

但结果还是不对,这是因为我们给节点没有提供右值引用版本

给节点提供右值引用版本

但结果还是拷贝构造

给insert进行完美转发

给insert相关的都进行完美转发

此时结果正常

移动构造和移动赋值注意事项 

 如果你没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任
意一个
(如果实现了这里面的任意一种,编译器会调用拷贝构造)。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类
型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,
如果实现了就调用移动构造,没有实现就调用拷贝构造。


如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中
的任意一个(如果实现了这里面的任意一种,编译器会调用拷贝赋值),那么编译器会自动生成一个默认移动赋值
。默认生成的移动构造函数,对于内
置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋
值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造
完全类似)


如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。

当存在析构或拷贝构造或构造时,我们可以强制生成移动构造和移动赋值

强制生成默认函数的关键字default:
C++11可以让你更好的控制要使用的默认函数。假设你要使用某个默认的函数,但是因为一些原
因这个函数没有默认生成。比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以
使用default关键字显示指定移动构造生成。
 

delete

 禁止生成默认函数的关键字delete:

 如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且只声明补丁
已,这样只要其他人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即
可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。

 这里以不想让Person对象拷贝为例

 

 继承和多态中的final与override关键字前面博客已经说过

将析构用delete修饰,在哪个区域都无法创建对象 ,因为创建的对象最后要调用析构

 

如果要创建对象只有一种方法, 使用new,new出来空间的被指针接收,指针不会调用析构函数

 如果在构造的时候new一块空间,这回导致资源泄露,因为析构被禁了

 此时手动delete会出错,因为要调析构,析构此时调不了

我们可以手动写一个释放空间的函数,调用这个函数即可

 

 这里的空间有俩层,destory只释放了_str所指向的空间,而ptr指向的空间没有被释放

可用这种方法解决

 


 

相关文章:

C++——C++11 第一篇

目录 统一的列表初始化 &#xff5b;&#xff5d;初始化 decltype ​编辑 nullptr STL中一些变化 右值引用和移动语义 左值引用和右值引用 总结 左值引用优缺点 右值引用&#xff08;将亡值&#xff09; 拷贝赋值和移动赋值 万能引用|完美转发 移动构造和移动赋值注意…...

Spring Data JPA 中 CrudRepository 和 JpaRepository 的区别

1 问题描述Spring Data JPA 中&#xff0c;CrudRepository 和 JpaRepository 有何区别&#xff1f;当我在网上找例子的时候&#xff0c;发现它们可以互相替换使用。它们有什么不同呢&#xff1f;为什么你习惯用其中的一个而不是另一个呢&#xff1f;2 CrudRepository 和 JpaRep…...

推荐几款好用的数据库管理工具

本文主要介绍几款常用的数据库管理软件&#xff08;客户端&#xff09;&#xff0c;包括开源/免费的、商用收费的&#xff0c;其中有一些是专用于 MySQL 数据库的&#xff0c;例如 MySQL Workbench、phpMyAdmin&#xff0c;有一些是支持多种 SQL、NoSQL 数据库的&#xff0c;例…...

DPDK — 性能优化手段

目录 文章目录 目录硬件布局层面的优化操作系统层面的优化Linux 操作系统版本应用程序层面的优化Cache 优化内存对齐内存预取SIMD 报文批处理DDIO使用高级 CPU 指令集硬件布局层面的优化 DPDK 在硬件布局层面的优化,主要体现在以下几个方面: CPU 频率的高低:CPU 频率越高,…...

Fedora Linux未来五年规划

Fedora 委员会一直致力于起草战略计划&#xff0c;以帮助 Fedora Linux 更好地发展。近日 Fedora 委员会公布了一份 “《未来五年的 Fedora Linux 》” 战略计划草案&#xff0c;这份草案里面包含了他们的雄心壮志&#xff1a;每周将 Fedora 的活跃贡献者人数增加一倍。 Fedora…...

【C++之容器篇】map和set常见函数接口的使用与剖析

目录前言一、set1. 简介2. 成员类型3. 构造函数(1) set()(2)set(InputIterator first,InputIterator last)(3)使用4. 拷贝构造函数和赋值运算符重载5. empty()6. size()7. insert()(1)pair<iterator,bool> insert(const K& key)(2)iterator insert(iterator pos,cons…...

虚拟DOM是什么

参考文章做的总结&#xff0c;如有不足之处请指正&#xff01; 在讲虚拟dom之前&#xff0c;先讲讲&#xff0c;为什么前端操作dom会导致页面性能降低&#xff1f; 先说几个概念 有助于后面的理解 什么是 JavaScript 引擎&#xff1f; JavaScript引擎是一个专门处理JavaScript脚…...

进程通信方式

无名管道( pipe )&#xff1a; 管道是一种半双工的通信方式&#xff0c;数据只能单向流动&#xff0c;而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。高级管道&#xff08;popen&#xff09;&#xff1a; 将另一个程序当做一个新的进程在当前程序进…...

强化学习基础知识

强化学习是一种机器学习方法&#xff0c;通过agent与environment的互动&#xff0c;学习适当的action policy以取得更大的奖励reward。本篇博客介绍强化学习的基础知识&#xff0c;与两类强化学习模型。 目录强化学习的基础设定policy based 强化学习的目标3个注意事项实际训练…...

LeetCode230218_148、654. 最大二叉树

给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。 递归地在最大值 左边 的 子数组前缀上 构建左子树。 递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回 nums 构建的 最大二叉树…...

WordPress 是什么?.com 和 .org 的 WordPress 有什么差异?

本篇文章会介绍这次WordPress 5.8核心版本所带来的其中一项新功能&#xff1a;内存块小工具&#xff08;Widget&#xff09;此次更新把小工具编辑设定的页面也改成用「内存块编辑」的概念&#xff0c;就跟内置的「古腾堡」编辑器一样&#xff0c;把所有元件都内存块化&#xff…...

java8新特性【2023】

Lambda表达式 新的一套语法规则 是一个匿名函数 Testpublic void test1(){Runnable r1 new Runnable(){Overridepublic void run() {System.out.println("线程A");}};r1.run();System.out.println("");Runnable r2 () -> System.out.println("…...

刷题记录:牛客NC51101Lost Cows

传送门:牛客 题目描述: (2≤N≤8,000) cows have unique brands in the range 1..N. In a spectacular display of poor judgment, they visited the neighborhood watering hole and drank a few too many beers before dinner. When it was time to line up for their ev…...

华为OD机试 - 不等式 | 备考思路,刷题要点,答疑 【新解法】

最近更新的博客 华为OD机试 - 寻找路径 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 最小叶子节点 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 对称美学 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 最近的点 | 备考思路,刷题要点,答疑 【新解法】华…...

GuLi商城-SpringCloud-OpenFeign测试远程调用

1. Feign 简介 Feign 是一个声明式的 HTTP 客户端&#xff0c;它的目的就是让远程调用更加简单。Feign 提供了HTTP请 求的模板&#xff0c;通过编写简单的接口和插入注解&#xff0c;就可以定义好 HTTP 请求的参数、格式、地址等信 息。Feign 整合了 Ribbon&#xff08;负载…...

阿里云_山东鼎信短信的使用(云市场)

目录山东鼎信API工具类随机验证码工具类进行测试Pom依赖(可以先导入依赖)创建controllerSmsServiceSmsServiceImplswagger测试(也可以使用postman)山东鼎信API工具类 山东鼎信短信官网 找到java的Api&#xff0c;复制下来 适当改了一下&#xff0c;为了调用(类名SmsUtils) p…...

基于虚拟机机的代码保护技术

虚拟机保护技术是基于x86汇编系统的可执行代码转换为字节码指令系统的代码&#xff0c;以达到保护原有指令不被轻易逆向和篡改的目的。 字节码&#xff08;Byte-code&#xff09;是一种包含执行程序&#xff0c;由一序列 op 代码/数据对组成的 &#xff0c;是一种中间码。字节是…...

Win10耳机有声音麦不能说话怎么办?麦克风说话别人听不到解决方法

网上找了一些解决办法&#xff0c;一般都是重复的&#xff0c;几个设置调来调去也就那样&#xff0c;没什么用 这种问题一般是“老式”一点的台式机会出现&#xff0c;提供的解决办法如下&#xff1a; 首先下载带面板的音频管理器&#xff0c;如realtek高清晰音频管理器&…...

The 22nd Japanese Olympiad in Informatics (JOI 2022/2023) Final Round 题解

交题&#xff1a;https://cms.ioi-jp.org/documentation A 给一个序列 a1,⋯,ana_1,\cdots,a_na1​,⋯,an​。 执行nnn个操作&#xff0c;第iii个操作为找出第iii个数前离其最近且与它相同的数的位置&#xff0c;把这两个数之间的数全部赋值aia_iai​。求最后的序列。 考虑第…...

openEuler RISC-V 成功适配 VisionFive 2 单板计算机

近日&#xff0c;RISC-V SIG 成功在 VisionFive 2 开发板上适配欧拉操作系统&#xff0c;目前最新版本的 openEuler RISC-V 22.03 V2 镜像已在 VisionFive 2 开发板上可用&#xff0c;这是 openEuler 推动 RISC-V 生态演进的又一新进展。下载链接​​https://mirror.iscas.ac.c…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...