1、前言概念
左值引用一直有这个概念。C++11中才出现了右值引用的概念。
注意本文只讨论左值引用和右值引用,但需要提前了解一下左值和右值。
// 以下的a、p、*p、b都是左值
int a = 3;
int* p = &a;
*p;
const int b = 2;
double x = 1.3, y = 3.8;
// 以下几个都是常见的右值
10; // 字面常量
x + y; // 表达式返回值
fmin(x, y); // 传值返回函数的返回值
简单来说,可以取地址的就是左值,无法取地址的就是右值。或者说在作用域内,内存可以常驻的就是左值,内存无法常驻的就是右值。
2、(非const的)左值引用 【避免对象拷贝】
T &v = XXX;这个样子的引用叫做左值引用。例如下面代码中,a就是左值引用。顾名思义,左值引用表示引用的内容是一个左值,代码中的a所引用的内容是x,而x是一个左值。
int x = 3;
int y = 4;
int &a = x; //正确
int &b = 6; //错误
int &c = x + y;//错误
左值类似于一个别名,主要是为了防止拷贝对象。左值引用只能指向左值(此处的指向二字,可能不太准确,理解意思即可),因为右值的临时分配的没有常驻内存,无法有别名。
3、const左值引用
带了const,就比较特殊了,const左值引用可以指向右值。如:
int x = 4, y = 5;
int &r = x + y; //错误
const int &t = x + y; //OK
所以带了const后的左值引用,所指向的内存就会常驻(不会被自动释放)。但是不能改变其值。
问:为什么const左值引用也可以引用右值?
答:在 C++11标准产生之前,是没有右值引用这个概念的,当时如果想要一个类型既能接收左值也能接收右值的话,需要用const左值引用,比如标准容器的 push_back 接口:void push_back (const T& val)。
也就是说,如果const左值引用不能引用右值的话,有些接口就不好支持了。
另外,const左值引用,本意上是指向一个不被(该引用本身)它修改的内存区域,本质上这个引用变量本身也就是一个常量,至于这个内存区域对应一个全局变量、局部变量、xvalue,无所谓啊。
如下比较可以看看:
void push_back1(int &val);
void push_back2(const int &val);
int x = 3, y = 5;
push_back1(x+y); //错误
push_back2(x+y); //正确
4、右值引用【延长对象生命周期】
左值引用和const左值引用貌似就够用了,那为啥还需要右值引用呢?
考虑一个场景1需求:为了效率,我不想拷贝构造,但是我又想改变返回值。
int x = 1,y = 2;
int &r = x + y; //无法编译通过,所以无法满足我的场景需求
const int &r = x + y; //无法改变内容,所以无法满足我的场景1需求
此时右值引用就应运而生。
右值引用就是对右值的引用,给右值取别名。主要作用是把延长对象的生命周期,一般是延长到作用域的scope之外。
int x = 3,y = 4;
int &&r = x + y; //编译通过
r = 14;//而且可以改变值
//注意,编译的时候需要加上 -std=c++11
右值引用 引用 右值,会使右值被存储到特定的位置。
也就是说,右值引用变量其实是左值,可以对它取地址和赋值。
再看一个场景2需求,如下代码,由于myFun的返回值是一个右值,所以b=myFun()会进入等号操作符。我的需求是需要修改b1的内容,由于参数是const引用所以无法修改b1内容。那如果我将const B &b1的const去掉呢,那么就编译错误了,因为参数b1是一个左值引用无法指向myFun()的返回值(其返回值是个右值)。
class B{
public:
B& operator=(const B &b1)//const不能去掉,否则编译失败
//B& operator=(B &b1)//编译失败
//B& operator=(B &&b1)//皆大欢喜
{
//需要修改b1里的一些内容
b1.Xxx= xxx;
free(b1.xxx);
return *(this)
}
};
B myFun(){
return B();
}
B b;
b = myFun();
虽然需求有些诡异,但是需要满足的需求只能通过右值引用了。同理使用&&来解决这个问题。只要将const B &b1改为B &&b1就可以了。既可以编译通过,也可以修改其内容。
参考:https://www.cnblogs.com/david-china/p/17080072.html
标签:const,右值,int,左值,C++,引用,b1 From: https://www.cnblogs.com/dongfangchun/p/18407208