逻辑自洽地区分【左值与右值】

前言

        由于不同的文章和书籍,对左值和右值的区分皆有不同,这里我只是给自己定了一个逻辑可以自洽的标准,供自己去区分左值和右值,所以本篇博客,属于一个笔记。

C++ primer对左值和右值的介绍

        C++中的表达式:要么是左值,要么是右值。而左值和右值是从C语言中继承过来的,在C语言中,为了帮助记忆,可以简单的认为左值可以位于赋值语句的左侧,右值则不能。这里其实也表达了一个隐藏的性质:左值可以被修改,右值不可以被修改

        但是在C++中,左值和右值的区分就复杂了很多,这也就是不同的文章、资料和书籍对左值和右值区分有不同的说法的原因。

        C++primer:“一个左值表达式的求值结果是一个对象或者一个函数,然而以常量对象为代表的某些左值实际上不能作为赋值语句的左侧运算对象”

        这句话的意思就是左值是一个指明对象的表达式,“常量对象不能做赋值语句的左侧运算对象”的意思就是const 左值,即使不可修改,但是依旧是左值。也就指出:左值分为可修改的左值和不可修改的左值(常量对象/const 左值)

        C++primer:“虽然某些表达式的求值结果是对象,但它们是右值而非左值”

        这句话意思,即使你的表达式结果指向的是一个对象,但是你位于赋值表达式的右侧,那这个对象就被当作右值,此时用到的是对象的值,也就是用的对象的内容,并不是这个对象。

        最后其总结了一句话:“当一个对象被用作右值时,用的是对象的值(内容);当对象被用作左值时,用的是对象的身份(对象在内存中存储的位置)”

        这也表达了一个观点:左值可以当右值使用,但是此时用的是左值指向的对象的内容,但是右值不能当左值使用,因为左值必须指明一个对象,右值压根没有指明的对象

        在了解这些之后,下面是总结的左右值的概念和区分

一、左值(可修改的左值 、不可修改的左值)

左值:用来指明一个对象的表达式,指向这个对象的内存区域,可以被取地址

        我们思考一下,左值一般用来干什么?
        我们在使用左值的时候,无非就是在赋值,将左值改变,那既然是要改变左值,就必须要求左值指明一个对象,也就必须要求左值要拥有存储空间,可以被取地址。

        (没有空间怎么改变?)

特殊情况:不可被改变的左值

        const 修饰的左值,不可被修改,不能出现在 ‘ = ’的左侧,但仍是左值

证明1

        因为左值是 有指明的对象,有存储空间且可以被取地址的,所以即使被const修饰,依旧满足上面的条件

证明2:(C++语法)

        使用左值引用与右值引用来证明

    const int x = 10;
   // x = 12; //虽然x不可出现在 ‘ = ’的左边
   // const int&& y = x;   //右值引用无法引用
    const int& z = x;    //左值引用可以引用,但必须是const,要保证权限
//                         从语法上证明,x仍为左值

二、右值(都不可被改变)

右值:表示一个值但不指明一个对象的表达式,不可以被取地址;如:字面常量,表达式,数组名,函数名,临时对象

数组名、函数名为右值原因:

        数组名与函数名都是地址常量,没有指明的空间存储,所以为右值;

临时对象为右值原因:

       首先要知道临时对象是如何产生的?

        临时对象一般是在 类型转换、对象拷贝的时候生成的,其任务就是将值拷贝一份,再赋值给接收对象。赋值结束后,临时对象也就销毁了,所以其生命周期的短暂,我们无法取到其地址,就认为临时对象是一个将亡值,被当作右值。

在C++11引入右值引用之后

        C++primer  提到了:“左值持久,右值短暂”的说法,也就是左值有持久的状态,右值是非持久的状态。这也正对应了上面所说的,左值可以取地址,右值不可以。因为我们没有理由去取一个即将销毁的变量的地址,是没有意义的。所以在取右值的地址时,在编译的时候也是会报错的。

        综上所述,总结了区分左右值并且逻辑自洽的观点:

        对一个表达式取地址,可以通过编译,那就是左值;反之则为右值。左值可以作为右值,此时是用到的对象的值/内容,右值不能作为左值

疑问提出????

 当然还有一点让我纠结:int a = 0;int b = a;在第二个语句中的a是什么值?
        正如《C++ primer》提到的,此时只是用到了a的内容,这里不同的是,int b = a中的a,这个我们通常称作变量表达式,该变量表达式就是右值,因为是取a中的内容。
        所以针对这里面的 a 是左值或者右值,根本不好去证明,只能从语言逻辑上来分析,因为你在对 a 取地址的时候,一定可以取到地址,说明a为左值,这没有问题。因为 &a 和       int b = a里面的a,表示的含义不同。
        那最后到底如何区分呢?不用过度纠结,不影响你的使用,就记住编译器允许取地址的就是左值,反之为右值,上面行不通的,语言逻辑分析即可!

  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

终将向阳而生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值