C++的左值 右值 左值引用 右值引用 大白话总结

Posted 长江很多号

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++的左值 右值 左值引用 右值引用 大白话总结相关的知识,希望对你有一定的参考价值。

1. 前言

对左值,右值,左值引用,右值引用,总是记得又忘记,忘记再放弃,放弃再学习。于是把之前从各路大神(@参考)文章学习的内容,做一个简单的总结。希望自己和看到文章的你,下次能够快速想起。

首先,在C++11中所有的值,要么左值,要么右值。
而左值引用,右值引用,都是引用,只不过一个爱上了左值,一个爱上了右值。

接下来详细说明之。

2. 左值 右值

C++对于左值和右值没有标准定义,但是有一个被广泛认同的说法:

(a) 可以取地址的,有名字的,非临时的就是左值
(b) 不能取地址的,没有名字的,临时的就是右值

可见立即数,函数返回的值等都是右值;而非匿名对象(包括变量),函数返回的引用,const对象等都是左值。

例子:

int a = b+c //a是左值,有变量名为a,通过&a可以获取该变量的地址,表达式(b+c)是右值
int d = func(5) //d是左值,func(5)是右值
int e = 5;//e是左值,5是右值

3. 引用

谈左值引用和右值引用之前,先复习一下引用。
说引用不得不说指针,所以这里同时说明引用和指针。

(1) 指针是一个变量,指向一个内存的地址(存的可以是其他对象或变量);引用是一个内存地址的别名。
(2) 从编译器的底层实现看,引用本质上也是一个变量,占4字节,它相当于一个指针常量(const *p)(需要了解细节打开这里
(3) 引用必须初始化,之后不能再被修改。
(4) 指针可能为空,引用不能为空。

3.1 引用的用途

引用常用于修饰函数参数,可以提高效率,例子和说明如下:

//声明了一个类,在下面我们要将这个类的对象作为函数参数类型来使用
Class Object
{
};

// 此函数参数是值传递,会产生一个临时对象
void fun1(Object obj)
{

}

// 此函数参数是引用传递,不用检查obj是否为空,同时,使用引用传递,可以避免产生临时对象
void fun2(Object &obj)
{
    
}

// 此函数参数是指针传递,需要检查obj是否为空,当然和引用一样,可以避免产生临时对象
void fun3(Object *obj)
{
    
}

4. 左值引用 右值引用

首先,这两家伙都是引用!引用是什么,是别名!
所以,他们一个是左值的别名,一个是右值的别名!或者说,一个绑定到左值,一个绑定到右值。
所以他们都要遵守,声明就一定要初始化的约定。

左值引用的基本语法:
type & 引用名 = 左值表达式;

右值引用的基本语法:
type && 引用名 = 右值表达式;

左值引用其是就是传统意义的引用,特别是C语言或C++98,左值引用引用,一个意思。比如上一节的函数
void fun2(Object &obj)
就是一个左值引用。我们直接称为引用也可以。

右值引用C++ 11新增的特性。右值引用用来绑定到右值。

右值引用作用:
绑定到右值以后本来会被销毁的右值的生存期会延长至与绑定到它的右值引用的生存期。
右值引用的存在并不是为了取代左值引用,而是充分利用右值(特别是临时对象)的构造来减少对象构造和析构操作以达到提高效率的目的。

左值引用只能绑定到左值,但常量左值引用 例外(它可以绑定非常量左值、常量左值、右值)。
右值引用只能绑定到右值,包括常量右值引用

上面虽然拗口,但是其实也能理解,本来名字都叫左值引用了,还非要作为右值的别名,这这这,这不是不讲武德嘛^^

例子:

int &a = 2;       // 左值引用绑定到右值,编译失败
int b = 2;        // b是非常量左值
const int &c = b; // 常量左值引用c,绑定到非常量左值b,编译通过
const int d = 2;  // 常量左值
const int &e = d; // 常量左值引用绑定到常量左值,编译通过
const int &f = 2;  // 常量左值引用f,绑定到右值,编程通过



int g;
int &&r1 = g;    // 右值引用,绑定左值,编译失败

如果右值引用,非要绑定左值,怎么办?用std::move()
例如

int g;
int &&r1 = std::move(g);    // 右值引用绑定左值,编译通过

std::move是什么鬼?它其是就是创造C++右值引用的目的之一!

右值引用被用于一些标准库,最常用的就是

std::move 移动语义
std::forward 完美转发

因为篇幅问题,我单独再开一个文章介绍这两哥们。

参考

简书-C++之左值、右值、左值引用、右值引用
知乎-c++ 左值引用与右值引用
c++中,引用和指针的区别是什么?

以上是关于C++的左值 右值 左值引用 右值引用 大白话总结的主要内容,如果未能解决你的问题,请参考以下文章

c++的左值(lvalue),右值(rvalue),移动语义(move),完美转发(forward)

5分钟搞懂C++左值引用和右值引用!

C++11 中的左值引用和右值引用的区别

引用左值与右值

具有适用于左值和右值的引用参数的 C++ 函数

对纯右值的左值引用的地址代表啥?