【C++】左值、右值、左值引用、右值引用

左值和右值

就变量而言,对于一些变量,我们只会读取并使用它们的值,而不会改变他们的值(只读);对于其余的变量,我们既会读取它们的值,有的时候还会改变它们的值(读写),这是很常见的。在C++中,前一种变量称为右值,后一种变量称为左值,例如:

int a = 1;	// a是左值,1是右值

C++中的左值和右值

稍稍不同的一点是,在C++中,一个变量是左值还是右值并不取决于我们如何使用它,这仅仅由它的类型和生成的方式决定,这是由C++标准规定的。(下文中提到的左值变量和右值变量均指的是C++标准中所规定的 “左值” 和 “右值”)

在C++中,我们可以读写左值变量,但我们不能(而不仅仅是 “不会” )改变右值的值(仅有的两个例外将在下文中提到)。不能对右值进行取址(这点不存在例外)。

C++中的左值表达式和右值表达式

在C++中,如果一个表达式表示了一个左值变量,那么把这个表达式称为 “左值表达式”;如果一个表达式表示了一个右值变量,那么把这个表达式称为 “右值表达式”。

例如,对于具有返回值的函数调用表达式,如果函数返回引用类型,那么函数调用表达式指示着返回值 “引用” 的变量,如果这个变量是左值(右值),那么函数调用表达式是左值(右值)表达式;如果函数返回其他类型,那么函数调用表达式指示着一个匿名的临时变量,这个匿名变量用于存放函数的返回值,这个匿名变量是一个右值,因此函数调用表达式是右值表达式。

C++中的常量左值、右值引用

尽管C++标准中的规定符合大部分实际情况,例如,数字类型的字面值(1、2、3、3.56、7 …)被规定为右值,而的确没有哪一个人会想要改变数字1的值,但仍然存在一些疏漏。

如果你细心观察,不难发现我们有时候会想要改变一些右值的值,而有的时候又希望一些左值具有不可改变的值。为了应付这种情况,C++标准中引入了两个例外。对于前者,我们可以通过右值引用来改变右值的值,对于后者,我们可以使用常量左值。

常量左值在声明时带有 const 限定符,这种变量必须初始化且初始化后变量值不能再改变,请看代码:

const int a = 10;	// 声明了常量左值a,初始化为10
a = 15;			    // 非法,试图通过赋值改变常量左值a的值

右值引用是对右值的 “引用”,正如通过左值引用可以改变左值变量的值一样,通过右值引用也可以改变右值变量的值。

  • 左值引用通过在变量名前加 & 声明,右值引用通过在变量名前加 && 声明。
  • 一条语句内允许定义多个引用,但每一个引用的名字前都要加上 & 或 &&。
  • 引用必须初始化。(请参考我的另一篇文章:引用的初始化
  • 引用不是对象,因此不存在引用的引用,也不存在引用的指针。

请看代码:

#include <iostream>

class A
{
public:
    int value = 10;
};

A test();

int main()
{
    A instance;						     // 类A的一个实例变量
    A &&a = test() , &b = instance;		 /* 定义一个A类型的右值引用a
                                            绑定到test()的返回值,定
                                            义一个A类型的左值引用b绑
                                            定到实例变量instance*/
    a.value = 15;
    std::cout << a.value << std::endl << b.value << std::endl;
    return 0;
}

A test()
{
    A a;
    return a;
}

运行结果:

15
10
发布了19 篇原创文章 · 获赞 23 · 访问量 3895

猜你喜欢

转载自blog.csdn.net/weixin_43737206/article/details/103494276
今日推荐