C++语言中的左值与右值,以及右值引用“&&”

        在学习C++ primer Plus的第八章“函数探幽”的过程中,我终于见到了以前一直不懂的“int && a”字样的语法结构。现在知道了,这个叫做“右值引用”,其特点就在于可以引用右值。那么究竟怎样理解“左值”和“右值”,以及“右值引用”呢?

        首先,通过一个直观的例子了解什么是左值和什么是右值。

int a;
a = 1;

        以上代码实现了对int型变量a的声明和赋值。其中赋值的部分可以理解为“将1赋予变量a”,在这里,等号的左侧是变量a,是“左值”,等号右侧的“1”是常量,是“右值”的一种形式。显然,这是一条合法的语句。那么,这个语句倒过来可以吗?答案是否定的。比如下面的代码:

1 = a;
a + b = c;

         这样的语句,都是无法通过编译的,编译器显示“error: lvalue required as left operand of assignment”,所以,“左值”就是一定要放在等号左侧的,“右值”就是一定要放在等号右侧的。

       一般而言,左值可以是变量(C++内置的变量或自己创建的变量类型,例如结构或者类等),或者指定的可以更改的内存块(比如通过new语句创建的没有名称的存放数据的内存块)。而右值是常量(例如const类型的量)或字面量(例如带双引号的字符串字面值或者直接数字)或者一些表达式(例如“a+1”、“x+y”等)。

        当然,书中对“左值”、“右值”知识的介绍并不是停留在这里,而是为了进一步介绍C++语言特有的“将引用作为函数参数”这一功能时所需要注意的事项做一些准备。

        将变量的值或指针作为函数的参数这一功能,C++语言与C语言基本相同。然而C++比C语言强大,就在于它还增加了“将引用作为函数参数”的功能。所谓“引用”,就是为被引用的变量取另一个名字,并对它进行操作。可以举一个简单例子如下:

int add_self (int & a) /// 传递引用变量
{
    a = a + 1;
    return a;
}

int add_self (int a) /// 传递变量的值
{
    a = a + 1;
    return a;
}

        这个函数可以实现将一个变量加一再返回的功能。传递变量的引用与直接传递变量值的区别,相信大家都明白,就是前者直接在函数中使用被引用变量,而后者则在函数中取变量的拷贝值进行运算。在调用函数之后,如果函数参量表中没有“const”字样,则被引用的变量可能被函数更改;而直接传递变量值的函数则不会改变。

        虽然“引用”这个功能很好用,但它也有着更严格的要求,即放入函数参量表中的参数必须与函数声明中的引用类型一致。比如说:

#include <iostream>
using namespace std;

void print (int & a);

int main()
{
    int a = 100;
    print(a);
    return 0;
}

void print (int & a)
{
    cout << "print a as reference: " << a << endl;
}

        上面这个程序可以正常运行,因为主函数中调用该函数时使用了变量名“a”本身,所以运行正常。

        但此时如果将“a”改为“a+1”,则编译时开始报错:

        “error: invalid initialization of non-const reference of type 'int&' from an rvalue of ...”

        即,若使用引用型参量表,则必须使用左值来初始化。

        相比之下,直接传递变量值的方法反而更不容易受限制,如下:

#include <iostream>
using namespace std;

void print (int  a);

int main()
{
    int a = 100;
    print (a);
    print(a+1);
    return 0;
}

void print (int  a)
{
    cout << "print a as reference: " << a << endl;
}

        该程序对左值(a)和右值(a+1)都可以正常运行,输出 100 和 101 两个数字。

        那么,如果将引用用于函数参量表,就没有办法使用右值了吗?

        当然有办法。那就是使用“int && a” ,即“右值引用”。

#include <iostream>
using namespace std;

void print (int && a);

int main()
{
    int a = 100;
    print(a+1);
    return 0;
}

void print (int && a)
{
    cout << "print a as reference: " << a << endl;
}

        该程序可以正常运行,输出“a+1”的值 101 。但同时,在这个程序中,如果将“print(a+1)”改为“print(a)”,编译将再次报错,“error: cannot bind 'int' lvalue to 'int &&'”,因为右值引用的函数只能使用右值。

        另外,这种右值引用的方法,不能像左值引用一样对被引内容进行修改,因为右值都是常量或者表达式,只存在于暂时存储中,不可以重复调用。故右值引用仅仅是一种扩展函数适应性的功能,可以用于函数重载等功能当中。(依据我当前的知识水平而言。)

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值