引用、左值与右值

我的理解



  引用是一个左值,而常量引用是一个右值。两者最关键的地方在于,左值可以被取到地址,而右值取不到地址,这个性质就决定了右值不能在 “=” 的左侧。

  从汇编角度去理解这个问题的话,就很好理解了,左值是一个内存单元里的数据,我们可以直接寻址找到它,而右值是一个立即数或者是寄存器里的值。

C与C++中的左值、右值



  C 中可以通过赋值号 “=” 简单地判断,比如

 int a = 42; // 表达式a是左值,字面值常量42是右值
    int b = 43; // 表达式b是左值,字面值常量43是右值

    a = b; // 表达式a和表达式b都是左值
    b = a; // 表达式a和表达式b都是左值
    a = a * b; // 表达式a是左值, 表达式a*b是右值

    int c = a * b; // ok,表达式c是左值,表达式a*b是右值
    a * b = 42; // error,表达式a*b是右值,右值不能出现在赋值操作符的左边
                //lvalue required as left operand of assignment

  但是在 C++ 中,由于自定义类引入的一些新的特性,这些就没那么简单了。

  当一个对象被用作右值的时候,用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。

  C++中常见的左右值如下:

    • 赋值运算符(=)的左侧运算对象必须是一个非常量的左值,其结果也仍然是一个左值。
    • 递增和递减运算符(++和–)必须作用于左值运算对象,前置版本将对象本身作为左值返回,后置版本则将对象原始值的副本作为右值返回。
    • 箭头运算符(->)作用于一个指针类型的运算对象,结果是一个左值。
    • 点运算符(.)分成两种情况: 
      • 如果成员所属的对象是左值,那么结果是左值。
      • 如果成员所属的对象是右值,那么结果是右值。
    • 条件运算符(? :)的两个表达式都是左值或者能转换成同一种左值类型时,运算的结果是左值;否则运算的结果是右值。
    • 取地址运算符(&)作用于一个左值运算对象,返回一个指向该运算对象的指针,这个指针是一个右值。
    • 内置解引用运算符*、迭代器解引用运算符*、内置下标运算符[]、容器下标运算符[]的求值结果都是左值。
    • 算术运算符的运算对象和求值结果都是右值。
    • 逻辑运算符(!,&&,||)的运算对象和求值结果都是右值。
    • 关系运算符(<,<=,>,>=,==,!=)的运算对象和求值结果都是右值。
    • 函数的返回类型决定函数调用是否是左值。 
      • 调用一个返回引用类型的函数得到左值。
      • 调用一个返回其他类型的函数得到右值。

记忆方法



  

  我的记忆规则是左值持久,右值短暂。

     左值是持久的,而右值要么是常量,要么是表达式求值所产生的临时对象。

两个错误例子



 

  例一:在递归时    

int func(Object &a) {
    if (...) return ...;
    Object b;
    func(b); //错误,b是一个临时变量,是右值,而引用需要的是左值
}

//改进方法
int func(const Object &a) { //常量引用需要的是右值
    if (...) return ...;
    Object b;
    func(b);
}

  例二:参数左值、右值匹配    

string func1 (string &s) {
    ...
    return string;
}
const string func2 (string &s) {
    ...
    return "1234";
}
int func3 (const string &s)  {
   ...
}

main () {
    strings s1 = "123456"; // s1 是左值
    string &s2 = func1(s1); //引用需要左值,而 func1() 返回左值,所以正确
    func3(s1); // func2() 需要的是常量引用,是右值,而 s1 是左值,但是C++有可变性,可以将左值传给右值,所以编译器可以通过。
    string &s3 = func2(s1); // func2()返回的是右值,而 s3需要的是左值,所以出错
}       

  

   

原文地址:https://www.cnblogs.com/Bw98blogs/p/8168088.html

时间: 2024-10-03 19:39:39

引用、左值与右值的相关文章

C++11之右值引用:从左值右值到右值引用

C++98中规定了左值和右值的概念,但是一般程序员不需要理解的过于深入,因为对于C++98,左值和右值的划分一般用处不大,但是到了C++11,它的重要性开始显现出来. C++98标准明确规定: 左值是可以取得内存地址的变量. 非左值即为右值. 从这里可以看出,可以执行&取地址的就是左值,其他的就是右值. 这里需要明确一点,能否被赋值不是区分C++左值和右值的区别. 我们给出四个表达式: string one("one"); const string two("two&

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

1.左值和右值的概念 左值是可以放在赋值号左边可以被赋值的值:左值必须要在内存中有实体:         右值当在赋值号右边取出值赋给其他变量的值:右值可以在内存也可以在CPU寄存器.         一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址. 2.引用 引用是C++语法做的优化,引用的本质还是靠指针来实现的.引用相当于变量的别名. 引用可以改变指针的指向,还可以改变指针所指向的值. 引用的基本规则: 声明引用的时候必须初始化,且一旦绑定,不可把引用绑定到其他

C++ 11 左值,右值,左值引用,右值引用,std::move, std::foward

这篇文章要介绍的内容和标题一致,关于C++ 11中的这几个特性网上介绍的文章很多,看了一些之后想把几个比较关键的点总结记录一下,文章比较长.给出了很多代码示例,都是编译运行测试过的,希望能用这些帮助理解C++ 11中这些比较重要的特性. 关于左值和右值的定义 左值和右值在C中就存在,不过存在感不高,在C++尤其是C++11中这两个概念比较重要,左值就是有名字的变量(对象),可以被赋值,可以在多条语句中使用,而右值呢,就是临时变量(对象),没有名字,只能在一条语句中出现,不能被赋值. 在 C++1

左值、右值、右值引用与move()、forward()

1.左值(lvalue):可以进行取地址(&)运算的是左值.或者有时候可以理解为 既能够出现在等号左边也能出现在等号右边的变量(或表达式). 2.右值(rvalue):不可以进行取地址(&)运算的是右值.或者有时候可以理解为 只能出现在等号右边的变量(或表达式). 常见的右值有 字面量.函数返回的临时对象,匿名对象等. 以上判断一个对象是左值还是右值并不完全正确. const int c_a = 10; //左值,但是不能被赋值,也就不能出现在 = 左边 //字符串字面值,可以取地址,是左

[转]C++11 左值、右值、右值引用详解

https://blog.csdn.net/hyman_yx/article/details/52044632 左值.右值 在C++11中所有的值必属于左值.右值两者之一,右值又可以细分为纯右值.将亡值.在C++11中可以取地址的.有名字的就是左值,反之,不能取地址的.没有名字的就是右值(将亡值或纯右值).举个例子,int a = b+c, a 就是左值,其有变量名为a,通过&a可以获取该变量的地址:表达式b+c.函数int func()的返回值是右值,在其被赋值给某一变量前,我们不能通过变量名

左值与右值引用 详解

说明 顾明思议 左值引用 就是对左值的引用 就是给左值取别名 右值引用 就是对右值的引用 就是给右值取别名 当改变别名是 该值也相应的改变 那么 何以区分哪些是左值哪些是右值呢? 左值 右值 在内存中有特定地址的量 在寄存器中的量 因为申请的变量会在内存中开辟一块地址 左值也叫有特定地址的量 比如: int a=10; //a 是左值 double b=1.3; //b 是左值 左值引用 int & Ta=a; //引用左值 故 是一个左值引用 double & Tb=b; //引用左值

(C++)关于i++和i++的左值、右值问题

1.什么是左值和右值? 左值就是出现在表达式左边的值(等号左边),可以被改变,他是存储数据值的那块内存的地址,也称为变量的地址: 右值是指存储在某内存地址中的数据,也称为变量的数据. 左值可以作为右值,但右值不可以是左值. 因此也只有左值才能被取地址. 2.举两个问题: int i = 0; (i++)+=i; //错误 (++i)+=i; //正确 int *ip = &(i++); //错误 int *ip = &(++i); //正确 3.为什么i++不能作左值? 我们来看i++和i

c++中的左值与右值

++(a++) a++相当于 int a; { int temp=a; a++; teturn temp; } 所以我们可以将++(a++)看成++temp;而temp 显然是一个右值,所以不能用啊~~ L-value中的L指的是Location,表示可寻址.The "l" in lvalue can be though of as locationR-value中的R指的是Read,表示可读.The "r" in rvalue can be thought of

C 语言中的左值和右值。以及对比数组名和指针取数组元素的区别。

左值:出现在赋值符左边的符号有时称为左值. 右值:出现在赋值符右边的符号有时称为右值. 编译器为每个变量分配一个地址(左值),这个地址在编译时可知,而且该变量在运行时一直保存于这个地址.相反,存储于变量中的值(它的右值)只有在运行时才可知.如果需要用到变量中存储的值,编译器就发出指令从指定地址读入变量值并将它存于寄存器. 可以看到,每个符号的地址在编译时可知. 对比一下几个式子: //常规变量 int a=1;//这里a作为左值出现,代表的是地址,即在a表示的这个内存地址存入数值1.即a代表的内