1。左值、右值、左值引用、右值引用
https://www.jb51.net/article/85549.htm
https://www.jb51.net/article/136337.htm
https://www.cnblogs.com/qicosmos/p/4283455.html
通常意义上,在C++中,可取地址,有名字的即为左值。
不可取地址,没有名字的为右值。右值主要包括字面量,函数返回的临时变量值,表达式临时值等。
可以接受右值的右值引用本身却是个左值
#include<iostream>
#include<utility>
#include<vector>
using
namespace
std;
int
f();
int
main() {
vector<
int
>vi(100);
int
i=42;
int
&&r1=i;
//error不能把右值引用绑到左值上
int
&&r2=10;
int
&r3=i;
int
&r4=10;
//error非常量引用不能绑到右值上
const
int
&r5=10;
//ok
int
&&r5=r2;
//error,r2是左值
int
&&r6=std::move(r2);
//ok,c++11std::move把左值转换为对应的右值引用类型。
int
&&r4=f();
//这个函数返回右值
int
&r5=vi[1];
//下标返回左值
int
&r6=r4;
//变量r4是左值
}
//左值引用表示一个对象的身份,右值引用表示对象的值
//返回左值引用的函数、赋值、下标、解引用和前置递增递减运算符都是返回左值。
//不能把右值引用绑定在它们上,但可以把左值引用绑在它们上
//返回非引用类型的函数、算术、关系、位以及后置递增递减运算符、取地址&都是返回右值
//不能把左值引用绑定它们上,但可以把const左值引用和右值引用绑定在它们上。
1、左值和右值的概念
左值是可以放在赋值号左边可以被赋值的值;左值必须要在内存中有实体;
右值当在赋值号右边取出值赋给其他变量的值;右值可以在内存也可以在CPU寄存器。
一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址。
2、引用
引用是C++语法做的优化,引用的本质还是靠指针来实现的。引用相当于变量的别名。
引用可以改变指针的指向,还可以改变指针所指向的值。
引用的基本规则:
声明引用的时候必须初始化,且一旦绑定,不可把引用绑定到其他对象;即引用必须初始化,不能对引用重定义;
对引用的一切操作,就相当于对原对象的操作。
3、左值引用和右值引用
3.1 左值引用
左值引用的基本语法:type &引用名 = 左值表达式;
3.2 右值引用
右值引用的基本语法type &&引用名 = 右值表达式;
右值引用在企业开发人员在代码优化方面会经常用到。
右值引用的“&&”中间不可以有空格。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
其实对于左值还是很好理解的,主要是对于右值是不好理解的,特别是代码的16行处:右值的例子。C++之所以设计出右值引用的语法,主要是因为对于类似b+1;这样的运算是发生在CPU寄存器上的,就不能对其取地址、赋值等操作,所以这类运算只能放在等号的右边,将其赋给其他的变量。若等号右边出现:&b,这样的操作是,也是右值,因为取地址符的操作也是在寄存器中完成的。所以不能作为左值。
和右值引用相关的概念比较多,比如:右值、纯右值、将亡值、universal references、引用折叠、移动语义、move语义和完美转发等.
在C++11中所有的值必属于左值、将亡值、纯右值三者之一。比如,非引用返回的临时变量、运算表达式产生的临时变量、原始字面量和lambda表达式等都是纯右值。而将亡值是C++11新增的、与右值引用相关的表达式,比如,将要被移动的对象、T&&函数返回值、std::move返回值和转换为T&&的类型的转换函数的返回值等
2。std::move()与完善转发std::forward()
右值引用移动构造:相当于剪切
左值引用拷贝构造:相当于拷贝再删除