本文整理自网文,如有冒犯,请告知删除。

左值(lvalue)和右值(rvalue)

左值(lvalue)和右值(rvalue)是c/c++中的基础概念。 简单理解为:有名字的是左值,没有名字的是右值。

  1. C
  • C语言中,左、右值均可为变量或表达式
  • C语言中,左值可出现在=号左边,也可出现在=号右边
  • C语言中,右值只能出现在=号右边
    int x, y;

    x = 1;
    y = 2;
    x = y;
    y = x;

    2 = x; //err
    x,y为左值2为右值
  1. CPP
  • CPP语言中,一个表达式会产生一个左值,或者一个右值,前者称为左值表达式,后者称为右值表达式。
  • CPP语言中,对于基本类型,左值和右值概念与C语言相同。
  • CPP语言中,对于自定义类型,右值允许通过它的成员函数进行修改。
    class A {
    public:
        A(int i) : _i(i) {}

        A& operator=(const A& other) {
            _i = other._i;
            return *this;
        }
        
        void set(int i) {
            _i = i;
        }

        int get() {
            return _i;
        }
    private:
        int _i;
    };

    int main() {
        A a(5);
        auto f = [&] () ->A {
            return a;
        }

        f().set(10);	//rvalue modify self.

        return 0;
    }
  1. 左值引用,右值引用
  • 左值引用:就是对左值进行引用

  • 右值引用:就是对右值进行引用

  • 引用只是变量的别名,本身不绑定内存。

  • 引用定义必须立即初始化。

  • 左值引用是具名变量值的别名,而右值引用则是不具名(匿名)变量的别名。

  • 左值引用通常也不能绑定到右值,但常量左值引用是个“万能”的引用类型。

  • 非常量左值只能接受非常量左值对其进行初始化。

int &a = 2;       // 左值引用绑定到右值,编译失败

int b = 2;        // 非常量左值
const int &c = b; // 常量左值引用绑定到非常量左值,编译通过
const int d = 2;  // 常量左值
const int &e = c; // 常量左值引用绑定到常量左值,编译通过
const int &b =2;  // 常量左值引用绑定到右值,编程通过

右值值引用通常不能绑定到任何的左值,要想绑定一个左值到右值引用,通常需要std::move()将左值强制转换为右值,例如:

int a;
int &&r1 = c;             // 编译失败
int &&r2 = std::move(a);  // 编译通过

右值两个特性: 可以调用成员函数。 只能被 const reference 指向。