c++中的左值引用和右值引用

int main()
{

    //报错:非常量引用的初始值必须为左值.(右值无法绑定到左值引用)
    //int& m = 2;

    //常量引用初始值为常量
    const int& n = 3;

    int a = 10;
    //a是左值,可以绑定到非常量引用r上
    int& r = a;

    //会提示错误:无法将右值引用绑定到左值
    //int&& r1 = a;

    //move()函数将左值 转换为 右值
    int&& r2 = move(a);
    /*
        右值引用 通常不能绑定到任何左值,要向绑定一个左值到右值的引用,通常需要std::move()将
        左值强制转换为右值.

    */

    cout << r << "\n";

    cout << "--------------" << "\n";

    cout << r2 << "\n";

    /*
    右值引用

    */

    int x = 100;

    //无法 使用 x+1 这样的常量值.
    //int& y = (x + 1);

    //这样就实现了 (这种方式叫做: 右值引用 )
    int&& rx = (x + 1);

    /*
        可能的实现原理:
        int x = 100;
        int* p = new int(x+1);
        int& rx = *p; (*p是表示 值)

        delete p; // 假如rx不再使用,系统自动删除p
        
    */

    return 0;
}

/*
引用就是别名(alias).所谓别名,就是对已存在的对象另起一个名字.本身含义并不难理解,
但与其它概念一组合,就成了使用难点.再加上新标准提出了新的一种引用-右值引用,
引用这一概念就变得更加难以理解和使用.


左值、右值
左值是可以放在赋值号左边可以被赋值的值;左值必须要在内存中有实体;
右值当在赋值号右边取出值赋给其他变量的值;右值可以在内存也可以在CPU寄存器。
一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址。
在C++11中所有的值必属于左值、右值两者之一,右值又可以细分为纯右值、将亡值.
在C++11中可以取地址的、有名字的就是左值,反之,不能取地址的、没有名字的就是右值(将亡值或纯右值).
举个例子,int a = b+c, a 就是左值,其有变量名为a,通过&a可以获取该变量的地址;
表达式b+c、函数int func()的返回值是右值,在其被赋值给某一变量前,我们不能通过变量名找到它,
&(b+c)这样的操作则不会通过编译.

右值、将亡值
在理解C++11的右值前,先看看C++98中右值的概念:C++98中右值是纯右值,纯右值指的是临时变量值、
不跟对象关联的字面量值。临时变量指的是非引用返回的函数返回值、表达式等,例如函数int func()的返回值,
表达式a+b;不跟对象关联的字面量值,例如true,2,”C”等.

C++11对C++98中的右值进行了扩充。在C++11中右值又分为纯右值(prvalue,Pure Rvalue)和
将亡值(xvalue,eXpiring Value)。其中纯右值的概念等同于我们在C++98标准中右值的概念,
指的是临时变量和不跟对象关联的字面量值;将亡值则是C++11新增的跟右值引用相关的表达式,
这样表达式通常是将要被移动的对象(移为他用),比如返回右值引用T&&的函数返回值、std::move的返回值,
或者转换为T&&的类型转换函数的返回值。

将亡值可以理解为通过“盗取”其他变量内存空间的方式获取到的值。在确保其他变量不再被使用、或即将被销毁时,
通过“盗取”的方式可以避免内存空间的释放和分配,能够延长变量值的生命期.

左值引用、右值引用
随着新标准(新标准往往就是新的技术)的提出,引用这一概念分成两类:左值引用、右值引用.
其中左值引用是最常用的一种,而右值引用则是语言使用上的一种革新.

其实对于左值还是很好理解的,主要是对于右值是不好理解的,特别是代码的16行处:右值的例子.
C++之所以设计出右值引用的语法,主要是因为对于类似b+1;这样的运算是发生在CPU寄存器上的,
就不能对其取地址、赋值等操作,所以这类运算只能放在等号的右边,将其赋给其他的变量.
若等号右边出现:&b,这样的操作是,也是右值,因为取地址符的操作也是在寄存器中完成的.所以不能作为左值。

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

左值引用通常也不能绑定到右值,但常量左值引用是个“万能”的引用类型。它可以接受非常量左值、
常量左值、右值对其进行初始化。不过常量左值所引用的右值在它的“余生”中只能是只读的。相对地,
非常量左值只能接受非常量左值对其进行初始化。

1.左值引用

左值引用的基本语法

Type &引用名 = 左值表达式;

引用的基本规则

(1)声明引用的时候必须初始化,且一旦绑定,不可把引用绑定到其他对象。
(2)对引用的一切操作,就相当于对原对象的操作。

2.右值引用

以上是最常见的引用方式,我们称之为左值引用。为了顺利区分左右值引用的概念,我们先来看下左右值的概念.
首先,左右值是表达式的属性。何为表达式?表达式由一个或多个运算对象组成。字面值和变量是最简单的表达式.
一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址。

int a = 1;

a + 1;    //a + 1 是表达式

在C++旧标准中,我们可以引用a,但却无法引用a+1,这是为什么呢?

这是因为,变量a被创建后,在它的作用域内是一直存在的。如此一来,它的引用是有存在意义的.
而a+1不是一个对象,在运算中临时存在于寄存器中,而寄存器中的值是时刻被刷新的,创建a+1的引用显得没有任何意义.
为了成功的使用类似于a+1这种右值的引用.C++新标准提出了区别于以往的引用-右值引用.

右值引用的基本语法

Type &&引用名 = 右值表达式;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值