左值、右值、左值引用、右值引用

【导读】:本文主要详细介绍了左值、右值、左值引用、右值引用以及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 << x << 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 << s << 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/339154.shtml

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

相关文章

itex将html转成pdf加水印,itext操作PDF文件添加水印

功能描述&#xff1a;添加图片和文字水印/**** 【功能描述&#xff1a;添加图片和文字水印】 【功能详细描述&#xff1a;功能详细描述】* param srcFile 待加水印文件* param destFile 加水印后存放地址* param text 加水印的文本内容* param textWidth 文字横坐标* param tex…

wxpython界面切换_wxpython实现按钮切换界面的方法

本文实例为大家分享了wxpython按钮切换界面的具体实现代码&#xff0c;供大家参考&#xff0c;具体内容如下 #-*- coding:utf-8 -*- import wx class TestFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self,None,-1,u登陆,size(370,280),stylewx.MINIMIZE_BOX| wx.…

jboss 4.3.0_JBoss BPM Suite 6.0.3版本的5个实用技巧

jboss 4.3.0上周&#xff0c;红帽发布了JBoss BPM Suite的下一个版本&#xff0c;标记为6.0.3 &#xff0c;已订阅的用户可以在其客户门户中使用。 如果您对本发行版中的新增功能感到好奇&#xff0c;请在客户门户网站上在线查看发行说明和其余文档 。 我们正在寻找一些简单的…

C 条件变量使用详解

condition_variable介绍在C 11中&#xff0c;我们可以使用条件变量&#xff08;condition_variable&#xff09;实现多个线程间的同步操作&#xff1b;当条件不满足时&#xff0c;相关线程被一直阻塞&#xff0c;直到某种条件出现&#xff0c;这些线程才会被唤醒。其主要成员函…

HTML5新布局元素布局,HTML5新的布局元素

HTML5相对于HTML4新增了一些布局元素新增布局标签的优点&#xff1a;⒈更加注重文档的结构内容而不是以什么形式展现出来⒉对人的友好&#xff0c;更加语义化&#xff0c;增加代码的可读性⒊对计算机友好&#xff0c;浏览器更容易解析新增布局标签的内容&#xff1a;新增的布局…

pannel添加的子窗体很大_超简单的地瓜粉焖子做法全解,零失败

总以为做焖子是一项很大的工程&#xff0c;如果朋友知道你会做焖子定会用惊叹的语气崇拜你&#xff0c;想多一项厨艺吗&#xff0c;想让家人吃上自己亲手做的焖子吗&#xff1f;使用艺琳农场的地瓜粉一定让你出手不凡的&#xff0c;超简单&#xff0c;往下看哦新手为了担心霍霍…

swagger api文档_带有Swagger的Spring Rest API –创建文档

swagger api文档使REST API易于使用的真正关键是好的文档。 但是&#xff0c;即使您的文档做得很好&#xff0c;您也需要设置公司流程的权利以正确&#xff0c;及时地发布它。 确保利益相关者按时收到是一回事&#xff0c;但是您也要负责API和文档中的更新。 自动完成此过程可轻…

多线程队列的算法优化

【导读】&#xff1a;本文主要讲解多线程队列的优化。多线程队列&#xff08;Concurrent Queue&#xff09;的使用场合非常多&#xff0c;高性能服务器中的消息队列&#xff0c;并行算法中的Work Stealing等都离不开它。对于一个队列来说有两个最主要的动作&#xff1a;添加&am…

购买台式计算机方案,购买电脑的注意事项有哪些?

随着电脑的应用与普及&#xff0c;电脑已经逐渐成为人们学习、工作、生活中不可缺少的工具。同时&#xff0c;电脑的价格在逐渐下降&#xff0c;很多用户开始准备选购自己的电脑。选购电脑要考虑用户的需求、价格承受能力、商家服务质量等。1、明确用户需求购买电脑之前&#x…

linux 文件大小_整理 | Linux下列出目录内容命令

IT服务圈儿有温度、有态度的IT自媒体平台来源&#xff1a;良许Linux(ID&#xff1a;liangxuxiansheng)在 Linux 中&#xff0c;有非常多的命令可以让我们用来执行各种各样的任务。当我们想要像使用文件浏览器一样列出一个目录下的内容时&#xff0c;大家第一时间想到的是 ls 命…

mysql caching_Spring Caching抽象和Google Guava Cache

mysql cachingSpring为缓存昂贵的方法调用提供了强大的现成支持。 这里详细介绍了缓存抽象。 我的目标是使用Spring Guava Cache涵盖Spring现在提供的4.0版本的较新的缓存实现之一。 简而言之&#xff0c;请考虑一种具有几种慢速方法的服务&#xff1a; public class DummyB…

多线程程序中操作的原子性

0. 背景原子操作就是不可再分的操作。在多线程程序中原子操作是一个非常重要的概念&#xff0c;它常常用来实现一些同步机制&#xff0c;同时也是一些常见的多线程Bug的源头。本文主要讨论了三个问题&#xff1a;1. 多线程程序中对变量的读写操作是否是原子的&#xff1f;2. 多…

2018秋计算机基础在线作业华师,18秋华师《计算机基础》在线作业3(标准答案).doc...

【奥鹏】[华中师范大学]华师《计算机基础》在线作业试卷总分:100 得分:100第1题,控制面板可实现__________。A、对计算机全面控制操作B、对硬件驱动、软件设置及Windows外观设置C、计算机的关闭操作D、删除计算机中的任意文件正确答案:B第2题,页眉和页脚的建立方法相似&#xf…

.net mvc actionresult 返回字符串_ASP.NET Core中的Action的返回值类型

在Asp.net Core之前所有的Action返回值都是ActionResult&#xff0c;Json(),File()等方法返回的都是ActionResult的子类。并且Core把MVC跟WebApi合并之后Action的返回值体系也有了很大的变化。ActionResult类ActionResult类是最常用的返回值类型。基本沿用了之前Asp.net MVC的那…

.jdeveloper_在JDeveloper 12.1.3中为WebSocket使用Java API

.jdeveloper介绍 最新版本的JDeveloper 12c&#xff08;12.1.3.0&#xff09;和WebLogic Server 12.1.3一起提供了一些新的Java EE 7功能。 其中之一是对用于WebSocket的JSR 356 Java API的支持。 实际上&#xff0c;从12.1.2.0版本开始就支持WebSocket协议&#xff08;RFC 645…

为什么程序员需要关心顺序一致性,而不是 Cache 一致性?

本文所讨论的计算机模型是Shared Memory Multiprocessor&#xff0c;即我们现在常见的共享内存的多核CPU。本文适合的对象是想用C 或者Java进行多线程编程的程序员。本文主要包括对Sequential Consistency和Cache Coherence的概念性介绍并给出了一些相关例子&#xff0c;目的是…

南科大计算机科学与技术专业如何,广州大学、深圳大学、汕头大学、南方科技大学,如何排名?...

广州大学、深圳大学、汕头大学和南方科技大学都是广东省内的一流大学。为了方便各位广东考生在填报志愿的时候有一个更好的了解&#xff0c;顺哥收集整理了这4所学校的一些信息。希望能帮助到大家。深圳大学2021年校友会排名省内第4&#xff0c;全国第57&#xff0c;中国一流大…

canoco5冗余分析步骤_打造高性能的大数据分析平台

大数据时代&#xff0c;大数据的应用与挖掘&#xff0c;大数据的分析和决策&#xff0c;大数据在经济社会的运行轨道上发挥着愈来愈重要的作用。对于大数据分析&#xff0c;现在好多互联网金融公司和传统的商业银行、证券基金公司都非常看重。个个都想在大数据分析中获得重要信…

C 迭代器iterator的实现原理

在经典的设计模式中&#xff0c;有一种迭代器模式&#xff0c;定义为&#xff1a;提供一个对象来顺序访问聚合对象中的一系列数据&#xff0c;而不暴露聚合对象的内部表示。迭代器的主要优点如下&#xff1a;访问一个聚合对象的内容而无须暴露它的内部表示。遍历任务交由迭代器…

html如何在画布上加层,在Canvas中嵌套Html

大概是这样的&#xff0c;现在需要根据一下上传的图片以及一些输入生成图片。本来打算用imagemagick的&#xff0c;但是后来觉得这样前后端要搞两份不同的代码&#xff0c;然后imagemagick使用起来远没有canvas用起来顺手啊。So&#xff0c;最终决定就用Canvas搞定它了&#xf…