zoukankan      html  css  js  c++  java
  • C++Review12_左值、右值、引用、右值引用和移动语义

    简单来说,再赋值符号“=”左边的就是左值;右边的就是右值;

    例如 x = y;

    左值 ,编译器认为x的含义是x所代表的地址;这个地址只有编译器知道。在编译时确定;编译器在特定的区域保存这个地址;给x赋值的意思就是往x所代表的地址的内存空间中赋值;

    右值,编译器认为y的含义y所代表的地址里的内容;这个内容是什么,只有运行时才知道;

    =================================================

    左值肯定是可修改的:意思就是出现在赋值符号左边所代表的地址上的内容一定是可以被修改的。换句话说,我们只能给非只读变量赋值。

    左值一般是一个变量,可以被赋值的变量。(const变量是一个例外只能做右值)。

    我的理解是可修改的变量才是左值(其实也不准确,应该是可以放在赋值符号左边;const变量也是某种意义上的左值,但是不能放在赋值符号左边;引用是变量的别名;

    粗略来讲,左值是一个有地址的变量 。

    对左值和右值的一个最常见的误解是:等号左边的就是左值,等号右边的就是右值。

    左值和右值都是针对表达式而言的,左值是指表达式结束后依然存在的持久对象,右值是指表达式结束时就不再存在的临时对象。

    一个区分左值与右值的便捷方法是:看能不能对表达式取地址,如果能,则为左值,否则为右值。

    此外讨论数组能不能作为左值

    数组是不能作为整体被修改的,所以数组不是左值;

    例如一个数组 a; a是不能作为左值的,可以把a[i]作为左值。

    数组是特殊的变量,只能一个个单独访问其元素,单独修改其元素。

    如果a作为左值,编译器会认为a表示的是首元素的首地址。所以只能访问到a[0]。

    进一步讲:

    左值就是能对表达式取地址、或(可修改的具名对象/变量。一般指表达式结束后依然存在的持久对象(其实就是分配了地址)。

    ================================================

    右值是右侧表达式所代表的内容。

    右值是表达式的值(不是引用),可以放在赋值右面。

    右值对于编译器来说,并没有分配一块内存来保存其地址,就是不能被寻址。是一个临时的对象;

    他可以是不占据内存空间的临时量或字面量,可以是不具有写入权的空间实体。

    ================================================

    通常讨论的引用都是指左值引用。

    左值引用还可以划分为:

      常量左值引用  (是一个万能引用类型):可以绑定到常量左值、常量右值、非常量右值、非常量左值;

      非常量左值引用:只能绑定到非常量左值;绑定到其他类型会导致很多问题,例如违反了常量的规定,以及使用一个被销毁的临时对象(非常量右值);

    ================================================

    右值引用:  //摘抄下方链接

    在C++11中,右值是由两个概念构成的,一个是将亡值(xvalue,eXpiring Value),另一个则是纯右值(prvalue,Pure Rvalue)

    纯右值不能取地址,一些运算表达式,比如1 + 3产生的临时变量值,也是纯右值。而不跟对象关联的字面量值,比如:2、‘c’、true,也是纯右值。此外,类型转换函数的返回值、lambda表达式等都是纯右值。

    在C++11中,右值引用就是对一个右值进行引用的类型。事实上,由于右值通常不具有名字,我们也只能通过引用的方式找到它的存在。通常情况下,我们只能是从右值表达式获得其引用。比如:
    T && a = ReturnRvalue();

    这个表达式中,假设ReturnRvalue返回一个右值,我们就声明了一个名为a的右值引用,其值等于ReturnRvalue函数返回的临时变量的值。

    在上面的例子中,ReturnRvalue函数返回的右值在表达式语句结束后,其生命也就终结了(通常我们也称其具有表达式生命期),而通过右值引 用的声明,该右值又“重获新生”,其生命期将与右值引用类型变量a的生命期一样。只要a还“活着”,该右值临时量将会一直“存活”下去。

    将亡值则是C++11新增的跟右值引用相关的表达式,这样表达式通常是将要被移动的对象(移为他用),比如返回右值引用T&&的 函数返回值、std::move的返回值(稍后解释),或者转换为T&&的类型转换函数的返回值(稍后解释)。

    右值引用和左值引用都是属于引用类型。无论是声明一个左值引用还是右值引用,都必须立即进行初始化。而其原因可以理解为是引用类型本身自己并不拥有所绑定对象的内存,只是该对象的一个别名。左值引用是具名变量值的别名,而右值引用则是不具名(匿名)变量的别名

    在C++11的程序中,所有的值必属于左值、将亡值、纯右值三者之一。

    ==============================================

    右值引用的作用:

    C++ 11中引入的右值引用正好可用于标识一个非常量右值。C++ 11中用&表示左值引用,用&&表示右值引用;

    右值引用根据其修饰符的不同,也可以分为非常量右值引用和常量右值引用。

    非常量右值引用只能绑定到非常量右值,不能绑定到非常量左值、常量左值和常量右值;如果允许绑定到非常量左值,则可能会错误地窃取一个持久对象的数据, 而这是非常危险的;如果允许绑定到常量左值和常量右值,则非常量右值引用可以用于修改常量左值和常量右值,这明显违反了其常量的含义。

    常量右值引用可以绑定到非常量右值和常量右值,不能绑定到非常量左值和常量左值(理由同上)。

     

    为了支持移动操作(包括移动构造函数和移动赋值函数),C++才引入了一种新的引用类型——右值引用,可以自由接管右值引用的对象内容。

     右值引用的使用:https://www.cnblogs.com/likaiming/p/9045642.html

    ================================================

    移动语义:

    C++11的移动语义:https://www.cnblogs.com/sunchaothu/p/11392116.html

    我理解的右值引用、移动语义和完美转发:https://www.jianshu.com/p/d19fc8447eaa

    ================================================

    相关链接:

    左值,右值,右值引用:https://www.cnblogs.com/wuchanming/p/3735907.html   //这个链接讲得很好

    C++的引用类型的变量到底占不占用内存空间?:https://www.cnblogs.com/karottc/p/cpp-reference.html

    C++右值引用:https://www.cnblogs.com/wuchanming/p/3735879.html

  • 相关阅读:
    ElasticSearch Index API && Mapping
    jQuery静态方法type使用和源码分析
    jQuery原型属性和方法总结
    jQuery原型方法first,last,eq,slice源码分析
    jQuery原型方法.pushStack源码分析
    解决浏览器窗口变小后右侧出现空白背景颜色或者图片不能全屏填充的方法
    js方法实现rgb颜色转换成16进制格式的代码的方法
    一个解决表单中的文字和文本区域(textarea)上对齐的方法
    jquery原型方法map的使用和源码分析
    jQuery原型方法each使用和源码分析
  • 原文地址:https://www.cnblogs.com/grooovvve/p/12368637.html
Copyright © 2011-2022 走看看