的引用_左值、右值、左值引用、右值引用

00604e74c131cf6de7a8d4bdb7b98a5a.png

【导读】:本文主要详细介绍了左值、右值、左值引用、右值引用以及move、完美转发。

左值和右值

左值(left-values),缩写:lvalues

右值(right-values),缩写:rvalues

直接上官网查,我一向倡导自己去懂得原理,而原理都是老外写的,当然我只是针对c 编程语言这样说。

https://msdn.microsoft.com/en-us/library/f90831hc.aspx

翻译:所有的c 表达,不是左值就是右值。

  • lvalues是指存在于单个表达式之外的对象。你可以把左值当成有名字的对象。所有的变量,包括常变量,都是左值。

  • rvalues是一个暂时存在的值存在于单个表达式之内的对象。

有点拗口(难理解),通俗来说就是,左值的生存期不只是这句话,后面还能用到它。

而右值呢,出了这句话就挂了,所以也叫(将亡值)。

它举了一个栗子:

#include   
using namespace std;  
int main()  {  
   int x = 3   4;  
   cout <endl;  
}  

在以上实例中,很显然,x是左值,3 4是右值。

它又举了一个栗子,来说明错误的使用和正确的使用

// lvalues_and_rvalues2.cpp  
int main()  {  
   int i, j, *p;  
  
   // 正确的使用: 变量是左值 
   i = 7;  
  
   // 错误的使用: 左边的操作 必须是 左值 (C2106)
   7 = i; // C2106  
   j * 4 = 7; // C2106  
  
   // 正确的使用: 被间接引用的指针是左值
   *p = i;   
  
   const int ci = 7;  
   // 错误的使用: 左边的操作 是 常量左值 (C3892)
   ci = 9; // C3892 
  
   // 正确的使用: 条件操作 返回了左值
   ((i 3) ? i : j) = 7;  
}  

左值引用、右值引用

左值引用:参考说明书《Lvalue Reference Declarator: &》,网站如下:

https://msdn.microsoft.com/en-us/library/w7049scy.aspx

使用语法:类型 &(引用符) 表达式

type-id & cast-expression 

翻译:

你可以把左值引用当成对象的另一个名字,lvalue引用声明由一个可选的说明符列表和一个引用声明符组成。

引用必须初始化,而且不能改变。

一个对象的地址可以 转化成 一种指定类型的指针 或者 转化成 一个 相似类型的引用。意义是相同的。

demo:

char c_val = 'c';
char *ptr = &c_val;
char &r_val = c_val;

不要混淆 取地址 和 引用,当&说明符前面带有类型声明,则是引用,否则就是取地址。

通俗来说 &在 ”=” 号左边的是引用,右边的是取地址。

右值引用:参考说明书《Rvalue Reference Declarator: &&》,网站如下:

https://msdn.microsoft.com/en-us/library/dd293668.aspx

使用语法:类型 && 表达式

type-id && cast-expression  

翻译:

Move Semantics:移动语义

右值引用使您能够区分左值和右值。Lvalue引用和rvalue引用在语法和语义上是相似的。

右值引用支持移动语义的实现,可以显著提升应用程序的性能。移动语义允许您编写将资源(例如动态分配的内存)从一个对象传输到另一个对象的代码,移动语义行之有效,因为它允许从程序中其他地方无法引用的临时对象转移资源。

为了实现移动语义,你在类中提供一个动态构造,和可选择的动态赋值运算符(operator=)。拷贝和赋值操作的资源是右值的可以自动调用移动语义。不像缺省的拷贝构造,编译器并不提供缺省的动态构造。

demo:

#include   
#include   
using namespace std;  
  
int main()  {  
   string s = string("h")   "e"   "ll"   "o";  
   cout <endl;  
}  

在Visual C 2010之前,每个调用 “ ”运算符会分配和返回一个新的临时的string对象,

“ ”运算符不能从一个string扩展到另一个,因为它不知道string是左值还是右值。如果源字符串都是lvalues,那么它们可能在程序的其他地方被引用,因此不能被修改。通过使用右值引用“ ”运算符能够修改那些不能在程序中别处引用的右值,所以现在“ ”运算符可以有一个string扩展到另一个。这可以显著减少字符串类必须执行的动态内存分配的数量。

为了更好地理解移动语义,考虑向向量对象插入一个元素的例子。如果超出了vector对象的容量,vector对象必须为其元素重新分配内存,然后将每个元素复制到另一个内存位置,以便为插入的元素腾出空间。当插入操作复制一个元素时,它创建一个新元素,调用copy构造函数将数据从前一个元素复制到新元素,然后销毁前一个元素。移动语义允许您直接移动对象,而不必执行昂贵的内存分配和复制操作。

Perfect Forwarding:完美转发

完美的转发减少了重载函数 避免了转发的问题。转发的问题出现在你写通用函数将引用作为参数,将这些参数由函数调用的时候。

举个例子,如果通用函数将 type const T&作为参数,那么调用函数不能修改参数的值。

如果通用函数 将 type T&作为参数,那么当参数是右值的时候,函数不能调用。

通常来说,为了解决上述的问题,你需要提供重载函数,既要有type const T&参数的函数,也要有type T&参数的函数。

结果呢,重载函数的数量随着参数数量呈指数递增。而右值引用能够使你只用一个函数就能适用于任意数量的参数。

原先的做法如下:

先写出所有适用的通用函数

struct W  
{  
   W(int&, int&) {}  
};  
  
struct X  
{  
   X(const int&, int&) {}  
};  
  
struct Y  
{  
   Y(int&, const int&) {}  
};  
  
struct Z  
{  
   Z(const int&, const int&) {}  
};  

再将带有不同类型的参数的函数用模板结合起来

template <typename T, typename A1, typename A2>  
T* factory(A1& a1, A2& a2)  {  
   return new T(a1, a2);  
}  

调用:需要根据适用的类型用相应的指针对接。

当调用的是左值时

int a = 4, b = 5;  
W* pw = factory(a, b);  

当调用的是右值时。但是,下面的示例中没有包含对工厂函数的有效调用,因为工厂将可修改的lvalue引用作为其参数,但是它是通过使用右值调用的:

这里要注意的是const int &是lvalue 而不是 rvalue

而2是rvalue,函数会编译不过。

Z* pz = factory(2, 2);  

为了解决这类问题,需要将模板函数修改成如下形式,右值引用可以适用const T& 和 T&形式的参数:

template <typename T, typename A1, typename A2>  
T* factory(A1&& a1, A2&& a2)  {  
   return new T(std::forward(a1), std::forward(a2));  
}  

经过上述修改,均可以调用,如下图代码所示:

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

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

相关文章

常用的开始→运行→输入命令集锦

gpedit.msc-----组策略sndrec32-------录音机Nslookup-------IP地址侦测器explorer-------打开资源管理器logoff---------注销命令tsshutdn-------60秒倒计时关机命令lusrmgr.msc----本机用户和组services.msc---本地服务设置oobe/msoobe /a----检查XP是否激活notepad--------打…

小白兔生小白兔-菲波拉契数列问题

有一对小白兔,从出生后第3个月起每个月都生一对小白兔,小白兔长到第三个月后每个月又生一对小白兔,假如小白兔都不死,问每个月的小白兔总数为多少&#xff1f; 这道题是典型的斐波拉切数列问题&#xff0c;其特点就是从第三列开始就等于前两列之和&#xff0c;算法&#xff1a;…

[html] 解释下你对GBK和UTF-8的理解?并说说页面上产生乱码的可能原因

[html] 解释下你对GBK和UTF-8的理解&#xff1f;并说说页面上产生乱码的可能原因 gbk和utf8的理解我们这里将以最简单最容易理解的方式来描述GBK和UTF8的区别&#xff0c;以及它们分别是什么。GBK编码&#xff1a;是指中国的中文字符&#xff0c;其它它包含了简体中文与繁体中…

控制反转_Spring:IOC 控制反转

Spring 概述Spring 是什么Spring 是分层的 Java SE/EE 应用 full-stack (全栈式) 轻量级开源框架。全栈式&#xff1a;对各种主流技术和框架都进行了整合&#xff0c;同时对三层架构都提供解决方案。轻量级和重量级的划分主要依据就是看它使用了多少服务&#xff0c;启动时需要…

TAB选项卡

TAB选项卡&#xff1a;下载用Java Script模仿各种作业系统的选项卡&#xff0c;老外就是牛&#xff0c;不仅支援多样式的即时切换&#xff0c;同时也支援每个选项卡是否附带图示的切换选项&#xff0c;选项卡也可以上下切换。 转载于:https://www.cnblogs.com/meetrice/archive…

巨蟒python全栈开发flask5

1.轮询&&长轮询&&长连接 2.GeventWebsocket 3.Websocket群聊 4.Websocket单聊 5.websocket握手 6.websocket解密 7.websocket加密转载于:https://www.cnblogs.com/studybrother/p/10717550.html

[html] js放在html的<body>和<head>有什么区别?

[html] js放在html的和有什么区别&#xff1f; 在浏览器解析HTML中的时候&#xff0c;如果在head标签中遇到了script标签并且是同步执行的&#xff0c;那么就会影响文档的加载&#xff0c;如果引入的过多的同步脚本文件 那么加载会变得非常怪异且卡顿&#xff1b;但是放在body…

最后一封“情书”

本来以为自己是可以按照自己的想法去维系 可是发现自己的矜持对于你是一种恐惧 从退出“水云”的那天我就懂了 真的懂了 我并没想到“关注”变成了“监视”&#xff0c;这是对我的一种侮辱&#xff0c;比任何都&#xff01; 心境不同了&#xff0c;没时间去做毫无意义的监视调查…

python向dict里添加_Python有条件地向Dict添加键

我试图从一个标题列表中生成dict&#xff0c;它将数据列“关联”到同一个实验。例如&#xff0c;我想转向&#xff1a;headers ["A_1","A_2","A_3","B_1","B_2","B_3"]进入^{pr2}$我的代码如下&#xff1a;cols …

Kubernetes探索学习005--Kubernetes的Controller模型和ReplicaSet伸缩

1.Kubernetes的controller pattern 需要认识到Kubernetes操作Pod的逻辑&#xff0c;都是由控制器来完成的。 查看之前写过的nginx-deployment的YAML文件 [rootkubernetes01 ~]# cat nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:name: nginx-deploym…

mysql 索引实战

mysql 索引实战 之前有个项目,已经充分用MYSQL的调优调了&#xff0c;速度感觉还可以.但发现索引没用上.于是调整之.首先,数据库中有date字段,是int类型的,入库时用php的time()入库的,现在的需求是要求1天之内的记录,我们来看具体的写法,先看原来的$query "select * from…

[html] 你对标签语义化的理解是什么?

[html] 你对标签语义化的理解是什么&#xff1f; 标签语义化的初衷是让正确的标签做正确的事情&#xff0c;但对于人来说&#xff0c;标签的语义除了在 tag 上体现&#xff0c;还可以从 id, class 上体现出来。而每个人对于标签的理解都会存在不同&#xff0c;因此强制规定哪个…

中医移动医疗_中医之极简移动医疗

来源&#xff1a;爱捣鼓网移动医疗是时尚名词。未来也必将初进医疗改革&#xff0c;其也将走进我们每一个人的生活&#xff0c;将来更是我们健康的贴身卫士和高效的个人预警机。移动医疗必将和手机融合。未来的手机不仅仅是娱乐&#xff0c;更是智慧生活的高级助手。现在&#…

编程语言

语言的分类 高级语言&#xff1a;python、Java、PHP...... ----->字节码 低级语言&#xff1a;C、汇编 ----->机器码 区别&#xff1a;高级语言有回收内存的机制&#xff0c;…

[html] 写H5和小程序有什么相同及不同的地方吗?

[html] 写H5和小程序有什么相同及不同的地方吗&#xff1f; 第一条是运行环境的不同。传统的HTML5的运行环境是浏览器&#xff0c;包括webview&#xff0c;而微信小程序的运行环境并非完整的浏览器&#xff0c;大家注意&#xff0c;我这里写的是“非完整的浏览器”&#xff0c…

javascript文字旋转效果

展开 | 隐藏 | 停止 | 旋转 | 改变旋转方向网页特效库背景特效整站模板导航特效时间特效图象特效文本特效代码&#xff1a;<html> <body> <style type"text/css"> BODY { background : #efefef; font : 12px Verdana; } A { color : #e70 } …

python的创始人、特点应用领域_python学习笔记(python发展介绍)

一、python介绍python的创始人为吉多・范罗苏姆(Guido van Rossum)目前python主要应用领域&#xff1a;・云计算・WEB开发・科学运算、人工智能・系统运维・金融&#xff1a;量化交易&#xff0c;金融分析等&#xff0c;作为动态语言的python&#xff0c;语言结构清晰简单&…

kubernetes ui 搭建

1、部署Kubernetes云计算平台&#xff0c;至少准备两台服务器&#xff0c;此处为3台 Kubernetes Master节点&#xff1a;192.168.0.111 Kubernetes Node1节点&#xff1a;192.168.0.112 Kubernetes Node2节点&#xff1a;192.168.0.113 2、每台服务器主机都运行如下命令 system…

[html] 你喜欢哪种布局风格?说说你的理由

[html] 你喜欢哪种布局风格&#xff1f;说说你的理由 flex个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

异常:由于代码已经过优化或者本机框架位于调用堆栈之上,无法计算表达式的值...

异常:由于代码已经过优化或者本机框架位于调用堆栈之上,无法计算表达式的值 原因&#xff1a; 如果使用 Response.End、Response.Redirect 或 Server.Transfer 方法&#xff0c;将出现 ThreadAbortException 异常。您可以使用 try-catch 语句捕获此异常。 Response.End 方法终…