首页 > 其他分享 >左值引用和右值引用

左值引用和右值引用

时间:2025-01-08 22:45:23浏览次数:1  
标签:const 右值 int 左值 地址 引用

左值引用和右值引用

左值和右值的定义

关于左值的定义,在《C++ Primer Plus》当中是这样定义的

左值是什么呢?左值参数是可被引用的数据对象,例如,变量、数组元素、结构成员、引用和解除引用的指针都是左值。非左值包括字面
常量(用引号括起的字符串除外,它们由其地址表示)和包含多项的表达式(例如x+y,函数的返回值)。在C语言中,左值最初指的是可出现在赋值语句左边的实体,但
这是引入关键字const之前的情况。现在,常规变量和const变量都可视为左值,因为可通过地址访问它们。但常规变量属于可修改的左值,而
const变量属于不可修改的左值。

提炼出关键区别可得出:可以直接通过地址访问的都是左值,不可以通过地址访问的是右值。左值又因为const分为可修改和不可修改两种。
举例如下:

int a=10;//a是左值,实际定义的时候是分配了一段地址,给起名为a,所以访问a就是访问这个地址
         //而10这个只是一个字面值,没有给他分配实际的地址,无法在其他地方访问到这个10
int &b=a;
int* p = &b; //此时的引用b和*p其实指向的都a这块内存,是可以通过地址访问的
const char *str ="ABC"//此处的ABC虽然也是字面值,但是他其实在常量,实际也是有地址,所以是左值
int a=b+c;//b+c也是一个右值
int a=fun(void)// 函数的返回值是右值

左值引用和右值引用的定义

左值引用

左值引用是我们最传统的的引用,引用是给一个已经定义变量起别名。这种引用的一个主要用途就是作为函数的形参,通过引用变量做形参,让函数操作这个函数的原始
数据。左值引用的在创建的时候必须初始化,而且初始话后不能被改变。左值引用在本质上是一个指针常量,所以函数不能返回一个本地变量的引用。

int a=10;
int &b=10;//错误,绑定的对象不是左值
int &b=a;//创建的时候必须绑定一个左值
int *const ref=&a;//此处的ref等价于b

void fun(const int &c);//常量引用,用作形参,防止引用绑定的对象的值被改变
const int &d=10;//此处是常量引用,此处的10是有地址的,在const区域

右值引用

右值引用是C++11新增的一种引用,他可以绑定到一个右值。右值引用实质上是给一个右值(本没有地址,更无法通过地址访问)划分一块地址,以后可以通过访问该右值引用(新划的地址)来访问这个右值。

int &&a=10;
int &b=a;//此处是一个左值引用,因为a已经有了地址
std::cout << a << std::endl;//打印10
std::cout << &a << std::endl;//本来一个右值10是没有地址的,但是我们给他使用了右值引用了以后就可以打印出他的地址以及打印出他的值了
int &&b=x+y;//此时的b只是获取当下x+y的值,以后x或y改变了,也不会改变b的值

i++与++i的分析

++i 是先加后用,先对i进行+1,然后返回i,此时返回的是一个左值,自始至终都是一个变量i
i++是先用后加,会先产生一个临时变量来保存i的值,以供使用,然后再给原来的i的值+1,还是保存在原来i的空间,但是返回的却是那个临时变量(即未自增前的变量),之后这个临时变量就会被释放,因此是
右值表达式。

由上图的这个例子可以看出,无论是i++还是++i,运行后i的值都会自增,对于i++这种情况,他会有一个临时变量才存储原来的值,因此会调用一次拷贝构造函数,导致性能的损失。

移动语义

引入右值引用的一个目的是为了实现移动语义

std::move()

move的作用是把一个左值强制变成一个右值

TODO:找到那天的临时笔记

完美转发

标签:const,右值,int,左值,地址,引用
From: https://www.cnblogs.com/clearskyy/p/18660731

相关文章

  • (java)内部类&lamada&方法引用
    前言:本部分内容关联性很强,尤其是了解由匿名内部类=>lamada表达式=>方法引用的递进关系,后续的内容中,方法引用可能用的不多,见到认识即可,但是匿名内部类和lamada表达式是非常通用的表达方式。1.内部类当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可......
  • rust学习十五.5、引用循环和内存泄露
    这个章节主要是为了引出弱引用这个奇怪的概念。说实在,这个没有什么太好写的,因为内容比较晦涩难懂! 在其它语言中,也常常存在所谓循环引用问题,和大部分问题一样,在其它语言中这些基本上都不是问题。但是在rust中,这是一个致命的问题。 例如有a,b两个点,a指向b,b指向a。如果根据截......
  • C语言中指针类型强转之后解引用出现问题
    函数中传入的参数是指针类型但是该指针类型是类型强转之后传入函数在函数调用过程中解引用指针的时候出现了keil-hardfault。首先查看MSP的值然后在内存中输入msp的值在反汇编窗口中输入地址找到出错的函数发现故障原因是在解引用指针时,由于指针类型出现强转,需要对......
  • Golang基础-值类型、引用类型区别
    在Go语言中,引用类型和值类型是两种不同的数据类型,它们在内存中的存储和传递方式有很大的区别。理解这两者的定义和适用场景对有效地编写Go代码至关重要。1.值类型(ValueTypes)定义值类型是指变量直接保存数据的副本。当你将一个值类型的变量赋值给另一个变量时,实际上是......
  • js Weakset和Set 对比,弱引用和强引用
    Set和WeakSet都保存对对象(如obj1)的引用,但它们处理这些引用的方式不同,这直接影响到垃圾回收的行为。强引用vs.弱引用强引用:当一个对象被Set引用时,Set持有的是对该对象的强引用。这意味着只要Set存在并且包含这个对象,JavaScript的垃圾回收机制就不会回收这个对象,即......
  • 6.4 Using tokens with references 将令牌与引用一起使用
    https://lalrpop.github.io/lalrpop/lexer_tutorial/004_token_references.htmlWhenusingacustomlexer,youmightwanttokenstoholdreferencestotheoriginalinput.Thisallowstousereferencestotheinputwhenthegrammarcanhavearbitrarysymbolssu......
  • Mybatis 映射文件中,如果 A 标签通过 include 引用了 B 标签的内容,请问,B 标签能否定义
    在MyBatis的映射文件中,如果A标签通过 <include> 引用了B标签的内容,那么B标签必须定义在A标签的前面。这是因为MyBatis在解析XML文件时是按顺序进行的,它需要在解析到 <include> 标签时已经知道被引用的内容。示例假设我们有一个映射文件 UserMapper.xml,其......
  • C++中值传递和引用传递的区别
    C++中值传递和引用传递的区别值传递:在函数调用时,传递的是实际参数的副本,因此函数内对参数的修改不会影响到实际参数。引用传递:在函数调用时,传递的是实际参数的引用,因此函数内对参数的修改会影响到实际参数。值传递示例代码:classA{public:A(){std::cout<<......
  • JavaScript的引用数据类型(Reference Data Types)
    Python基础Python是一种广泛使用的高级编程语言,凭借其简单易读的语法、丰富的库和框架、以及强大的社区支持,Python在数据科学、机器学习、网络开发、自动化脚本等多个领域中得到了广泛应用。本文将介绍Python的基础知识,包括语法、数据结构、控制结构、函数、模块与包等内容......
  • uni-app 资源引用(绝对路径和相对路径)方法汇总
    ......