• [C++]左值和右值(LValue and RVaule) C++11版


    C++11中对LValue和RValue的界定更加详细而合理(但是也更加麻烦了)

    1章节:C++11的新分类介绍

    2章节:不同值之间的转换

    3章节:对一些常见的表达式,如何区分他们是什么值?

    1. 表达式分类

    所谓Value,是对表达式而言的。一个表达式可以分为以下几种Value,下边详细说明

    1.1. lvalue(左值)

    lvalue指代一个函数或者对象。例如:

    1. E是指针,则*E是lvalue
    2. 一个函数的返回值是左值引用,其返回值是lvalue。例如int& foo();

    1.2. xvalue(expiring value,临终值)

    xvalue指代一个对象,但是和lvalue不同,这个对象即将消亡。具体来说,xvalue是包含了右值引用的表达式。因为右值引用是C++11新引入的东西,所以xvalue也是一个新玩意。例如:

    1. 一个函数的返回值是右值引用,其返回值是xvalue。例如int&& foo();

    1.3. glvalue(generalized lvalue,泛左值)

    glvalue即lvalue和xvalue的统称。

    1.4. rvalue(右值)

    rvalue是xvalue和prvalue的统称。因为引入了右值引用,rvalue的定义在C++中被扩大化了。

    1.5. prvalue(pure rvalue,纯右值)

    prvalue指代一个临时对象、一个临时对象的子对象或者一个没有分配给任何对象的值。prvalue即老标准中的rvalue。例如:

    1. 一个函数的返回值是平常类型,其返回值是rvalue。例如int foo();
    2. 没有分配给任何对象的值。如5.3,true。

    2. 表达式值类型的转换

    glvalue → prvalue

    其实表达式的转换,只有以上一途,也就是

    • lvalue → prvalue
    • xvalue → prvalue

    2.1. lvalue → prvalue

    这个很常见:glvalue(lvalue和xvalue)可以隐式转换为prvalue来满足需求。例如:

    int& foo(int val) // 函数接受prvalue
    {
        int a = val + 1;
        return a;
    }
    
    int main()
    {
        int i = 5;
        cout << foo(4) << endl; // 传递进去一个prvalue
        cout << foo(i) << endl; // 传递进去一个lvalue
        cout << foo(foo(i)) << endl; // foo(i)返回lvalue,传递至外层函数
        system("pause");
    }
    

    当然,这个函数写的不大好,不应该将临时对象传递出函数的~

    如果将foo改写为下面这样,上边的代码就不能工作了,因为prvalue→lvalue是不成滴~

    int& foo(int val)
    {
        return val + 1;
    }
    

    2.2. cv-qualifier的解除

    在其他转换中,const转换是不能去除的,但是glvalue到prvalue的转换是可以去除的。这个说辞比较晦涩,其实十分常见,比如:

    const int a = 5;
    int b = a; // b = ? 这个需要右值,所以把a先转为右值,同时丢弃了const限定词
    

    3. 表达式值类型的判定

    C++的每一个表达式都有其值类型,换句话说,任何表达式,都属于以下三者之一:lvalue,xvalue,prvalue。

    如果是简单的表达式自然很好理解,如上一节所举的变量、常量以及返回值。但是大部分情况都要复杂得多。

    2.1. C++内建操作的判定

    这个就要具体操作具体分析了。C++的内建操作对操作数的类型做出了详细的界定,对整个操作代表的类型也做出了详细的界定。例如:

    分配运算 op1 = op2。op1是lvalue,op2是rvalue。整个操作是lvalue

    2.2. 用户定义的操作

    用户定义操作,无非就是自建函数。(恩,没错,C++的操作符重载也是函数重载~~)操作数等价于函数参数,操作yield值相当于函数返回值。其类型都由用户界定。例如:

    1. int foo(int); 参数是prvalue,返回值是prvalue。
    2. int& foo(int); 参数是prvalue,返回值是lvalue。u
  • 相关阅读:
    【转】关于char * 与 char[]
    网页打印js代码
    无法用排他锁锁定该数据库,以执行该操作。 (Microsoft SQL Server,错误: 5030)
    CKEditor使用笔记
    FormView作为单独编辑页笔记
    用WindowsMediaPlayer控件写个WinForm播放器
    ListView搭配DataPager控件实现分页笔记
    如何禁用ViewState
    C#获取本机IP搜集整理7种方法
    ListView高效率分页笔记
  • 原文地址:https://www.cnblogs.com/SelaSelah/p/2572121.html
Copyright © 2020-2023  润新知