C++-详解C++11中的左值,左值引用,右值,右值引用

目录

一.C语言中对左值和右值的定义

        1.左值

        2.右值

二.左值引用和右值引用

        1.左值引用

        2.右值引用

        3.左值引用给右值取别名

       4.右值引用给左值取别名

三.移动构造和移动赋值

        1.移动赋值

        2.移动拷贝

​编辑​编辑

四.完美转发

        1.先看一道试题:

一.C语言中对左值和右值的定义

        C语言-数据对象,左值,右值-CSDN博客

        1.左值

                

                 定义:

                        左值是一个表示数据的表达式(比如变量名或解引用的指针)。

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

                        定义时const修饰后的左值,不能给他赋值,但是可以获取它的地址。

#include <stdio.h>

int main(void)
{
	const int a = 10;

	int b = a;

	return  0;
}

                对于int b = a;的解释:

                                 我们知道a是一个左值,但是同时右值本身又不可以是左值,那么这个a放到赋值运算符右边合理吗?

                                        其实这个是当我们将一个变量放到赋值运算符的右边时,会自动取出它的存储空间空间中的数据,而这个数据是右值。

        

        2.右值

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

                内置类型的右值   :纯右值。

                自定义类型的右值:将亡值。

二.左值引用和右值引用

        1.左值引用

                定义:左值引用就是左值的引用,给左值取别名。

                

        2.右值引用

                定义:右值引用就是右值的引用,给右值取别名。

                

                右值不可以被更改,但是右值引用可以被更改。 

        3.左值引用给右值取别名

                

                a + b这个表达式的值属性是保存在一个临时变量中的,临时变量具有常性 

       4.右值引用给左值取别名

                
                
                
                
                
                

三.移动构造和移动赋值

        1.移动赋值

string Func()
{
	string str("xxxxxxxxxx");

	return str;
}

int main(void)
{
	string ret;
	ret = Func();
	return  0;
}

        如果此时我们给的拷贝构造和赋值重载是这样的:

         

        此时就像我们的过程图中描述的一样,数据在从str到ret中的过程中发生了多次深拷贝,拷贝到没有什么,我们的计算机对于拷贝的处理是非常的快的,但是每次深拷贝时都会开辟新的空间,这个过程效率就很低了。

        解决办法:

        将赋值重载函数,写一个重载函数:

        此时程序的过程图就变为:

        

        移动赋值:

                内置类型的右值:将亡值。

                将亡值:马上就要被清理的自定义类型的对象。

                此时调用Func()产生的返回值(临时对象)就是一个将亡值。这个将亡值会被编译器处理成右值,所以此时ret=Func()会被调用

                        

                同时这个将亡值在这个表达式结束后就会被清理,但是这个临时对象中保存这我们想得到的数据,那么此时我们只需要将ret和这个临时对象中的数据进行互换就可以了。

                此时经过上面的操作,最后的赋值操作中我们并没有开辟新的空间,同时又近似的实现了深拷贝的操作。

                所以此时我们程序的效率提高了。

                

                上面的代码并不会发生移动赋值的情况!因为rett并不是自定义类型的右值,如果此时发生移动赋值,如果在此之后我们在想使用rett对象时,此时就会产生错误。

                但是:

                 

                这样程序是会发生移动赋值的,虽然move函数在调用完之后并不会改变rett对象本身是左值的属性,但是move函数的返回值可以让编译器认为此时rett对象是一个将亡值,可以发生移动赋值。

        2.移动拷贝

                在同一行代码中发生多次构造会被编译器优化为一次。

                虽然就像上图说的一样,经过编译器的优化,已经提高了我们程序的效率的,但是此时可不可以先移动赋值一样发生交换呢,做到一个新空间都不开辟呢?

                 移动构造:

                        此时只需要我们对拷贝构造函数进行改造:
                        

                                      

                        此时在编译器优化时会将str看成一个将亡值(右值),然后和ret进行交换。

                        所以当我们有了移动构造再来看移动赋值的代码:

                           

              此时1到2过程就不会在去调用深拷贝的拷贝构造了,直接调用移动拷贝就可以了。

                        两个疑惑:

                       

                          诚然我们在处理上面这样的情况时,确实应该在return中加move,但是如果没有编译器也会给我们进行优化的。

                                                        如果将返回值改为string&的,此时会产生两个问题

                                       a.因为str是局部对象,所以在出函数作用后会释放空间,所以此时会产生野指针的问题。

                                       b.string&后编译器不会在将str优化为右值,也就不可以发生移动构造了。

                

             左值引用的核心价值是减少拷贝,提高效率。

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

         

四.完美转发

        1.先看一道试题:

void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
template<typename T>
void PerfectForward(T&& t)
{
	Fun(t);
}
int main()
{
	PerfectForward(10);//右值
	int a;
	PerfectForward(a);// 左值
	PerfectForward(std::move(a)); // 右值
	const int b = 8;
	PerfectForward(b);// const 左值
	PerfectForward(std::move(b)); // const 右值
	return 0;
}

                 代码的运行结果是:

                 a.为什么此时函数模板中的明明是右值引用但是左值右值都可以接受?

                        

                        因为此时图中的引用是万能引用,因为此时函数模板的T是推导出来的。

                        

                b.为什么程序中即存在左值引用又存在右值引用但是却输出的结果都是左值引用呢?

                        因为在函数中Fun(t)即使是右值编译器也会将他看成左值。

                        解决方法:       

void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
// std::forward<T>(t)在传参的过程中保持了t的原生类型属性。
template<typename T>
void PerfectForward(T&& t)
{
	Fun(std::forward<T>(t));
}
int main()
{
	PerfectForward(10);// 右值
	int a;
	PerfectForward(a);// 左值
	PerfectForward(std::move(a));// 右值
	const int b = 8;
	PerfectForward(b);// const 左值
	PerfectForward(std::move(b));// const 右值
	return 0;
}

         forward<T>保持此时数据的左右值属性。(完美转发)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

外汇天眼:8家平台被监管拉黑,其中1家为假冒JP Morgan

就在最近&#xff0c;有八家未经监管授权的外汇交易公司被监管机构拉黑&#xff0c;其中有一家为假冒JP Morgan。具体新闻如下&#xff1a; 英国FCA对未授权平台Gens Markets发出警告 上周&#xff0c;英国金融行为监管局&#xff08;FCA&#xff09;对未经过监管授权的外汇平…

Kotlin学习之集合

原文链接 Kotlin Collections 现代的软件一般比较复杂&#xff0c;程序语言中的基本数据类型往往不能满足需要&#xff0c;除了基本的数据类型以外&#xff0c;还有对象的容器也非常的重要&#xff0c;比如线性容器&#xff08;数组&#xff0c;列表和Set&#xff09;和二维容…

Python提取PDF表格(基于AUTOSAR_SWS_CANDriver.pdf)

个人学习笔记&#xff0c;仅供参考。 需求&#xff1a;提取AUTOSAR SWS中所有的API接口信息&#xff0c;用于生成C代码。 此处以AUTOSAR_SWS_CANDriver.pdf为例&#xff0c;若需要提取多个SWS文件&#xff0c;遍历各个文件即可。 1.Python包 pdfplumber是一款完全用python开…

销量上不去,消费者纷纷回归直屏,折叠手机成为电子垃圾

折叠手机成为安卓手机创新的噱头&#xff0c;不过随着更多消费者使用了折叠手机&#xff0c;折叠手机正迅速走下神坛&#xff0c;用过的消费者都说体验太差&#xff0c;纷纷抛弃这种手机&#xff0c;而在二手市场价格又达到骨折&#xff0c;可以说折叠手机正成为电子垃圾。 折叠…

Ilya Sutskever:师从Hinton,“驱逐”奥特曼,一个改变AI世界的天才科学

ChatGPT 已经在全球爆火&#xff0c;但大众在两周之前似乎更熟悉Sam Altman&#xff0c;而对另一位创始人 Ilya Sutskever 却了解不多。 直到前几天因为OpenA眼花缭乱的政权争夺大戏&#xff0c;OpenAI 的首席科学家Ilya Sutskever的名字逐渐被世人所知。 Ilya Sutskever在科…

Win7 SP1 x64 安装 Python 出错解决方法

1 双击安装 python-3.7.9.exe &#xff0c;提示出错&#xff0c;log.file 显示需要 KB2533623&#xff0c;但在Microsoft Update Catalog 没有搜到&#xff0c;实验 KB4474419 也可以。 2 Microsoft Update Catalog 搜索 KB4474419 并下载&#xff0c;安装&#xff0c;重启电脑…

如何使用ArcGIS Pro制作一张北极俯视地图

地图的表现形式有很多种&#xff0c;经常我们看到的地图是以大西洋为中心的地图&#xff0c;还有以太平洋为中心的地图&#xff0c;今天要给大家介绍的地图是从北极上方俯视看的地图&#xff0c;这里给大家讲解一下制作方法&#xff0c;希望能对你有所帮助。 修改坐标系 制作…

前端开发学习 (三) 列表功能

一、列表功能 1、列表功能 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compa…

组装自己的稳定扩散模型

在本文中&#xff0c;我们将利用 Hugging Face Diffusers 库的组件实现自己的稳定扩散模型&#xff0c;可以像 diffuser.diffuse() 一样简单地生成图像。 在线工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编…

sqli-labs靶场详解(less11-less16)

目录 less-11 less-12 less-13 less-14 less-15 less-16 提交参数后 动态参数不存在url中 存在于post表单中 于是在表单中进行注入点测试 先看一看这种提交数据的关卡输入提交后会有什么反应 unameadmin&passwdadmin&submitSubmit 输出 usernameadmin passwordadmin un…

mongodb查询数据库集合的基础命令

基础命令 输入show dbs 命令&#xff0c;查看数据库 db查看当前正处在哪个数据库 创建或进入要使用的数据库&#xff0c;命令&#xff1a;use 数据库名字 刚创建的数据库数据库名字 并不在数据库的列表中&#xff0c; 要显示它&#xff0c;我们需要向 数据库名字 数据库插…

MFC哈希实现 目标:知道初始密码的人,才能改密码及登录。只知道登录密码只能登录。避免密码直接写在代码里或本地,通过软件评估报告。----安全行业基础5

一种简单的登录设计&#xff0c;密码保存在本地。&#xff08;直接MD5不安全&#xff0c;别人可以更换本地的密码,得再加一层算法就相对安全一点&#xff09; 当然也可以用加密机或专门存密码的系统来实现&#xff0c;就过于复杂。目标&#xff1a;1、为了避免密码直接写在代码…

使用shell快速查看电脑曾经连接过的WiFi密码

此方法只能查看以前连接过的wifi名称和对应的密码 查看连接过的WiFi名称netsh wlan show profiles查看具体的WiFi名称netsh wlan show profile name"你的wifi名称" keyclear

plt绘制表格

目录 1、绘制简单表格 2、将字体居中 3、为每个表格添加背景 4、添加透明度 5、不显示表格标题 6、将pandas的表格列转行显示 7、关闭表格边框 8、设置表格长宽、字体大小 9、利用色系指定表格颜色 10、修改字体颜色、边框粗细 1、绘制简单表格 import pandas as pd…

「阿里巴巴」裁撤量子实验室!

据内部消息&#xff0c;阿里巴巴达摩院由于预算及盈利等原因&#xff0c;已经撤裁旗下量子实验室。此次&#xff0c;共计裁减30余人。 达摩院官网已撤下量子实验室的相关介绍页面。上图&#xff1a;早先关于量子实验室的相关介绍&#xff1b;下图&#xff1a;现在达摩院官网“实…

十分钟搭建VScode C/C++运行环境

一、下载配置vscode 1.下载安装VScode 地址&#xff1a;https://code.visualstudio.com/download 下载后&#xff0c;运行安装程序 (VSCodeUserSetup-{version}.exe)。这只需要一分钟。安装程序会将 Visual Studio Code 添加到环境变量中%&#xff0c;可以使用CMD键入“code”…

主播直播表现力

主播表现力:全面提升你的直播效果 一、语言表达 主播的语言表达是直播的关键。优秀的语言表达能够让观众感到亲切和舒适&#xff0c;增加观众的参与度和忠诚度。以下是一些提升语言表达的建议: 1.清晰简洁:尽量使用简单易懂的词汇和句子结构&#xff0c;避免过于复杂的表达。…

C#实体类与XML互转以及List和DataTable转XML的使用

引言 在C#开发中&#xff0c;数据的存储和传输是非常常见的需求。使用XML作为数据格式有很多优点&#xff0c;例如可读性强、易于解析等。而实体类、List和DataTable是表示数据模型的常用方式。本文将介绍如何在C#中实现实体类、List和DataTable与XML之间的相互转换&#xff0c…

好用的样式动画库集合(css、js)

文章目录 前言一、Animate.css二、Anime.js三、CSShake四、Hover.css五、AniJS六、Animista七、Tachyons-animate八、Sequence.js九、Infinite十、OBNOXIOUS.CSS十一、MOTION UI十二、Keyframes.app十三、AnimXYZ十四、Whirl十五、Hamburgers十六、Vivify十七、Magic Animation…

【2021研电赛】智能胸外按压电除颤一体仪

本作品介绍参与极术社区的有奖征集|分享研电赛作品扩大影响力&#xff0c;更有重磅电子产品免费领取! 团队介绍 参赛单位&#xff1a;上海理工大学 参赛队伍&#xff1a;上理电感队 指导老师&#xff1a;闫士举 参赛队员&#xff1a;夏鹏、李宪龙、张涛 获奖情况&#xff1a;…