左值和右值
int i = 10;//对象:一块内存区域
i =20;
左值:能在赋值语句等号左侧的东西,它代表了一个地址
右值:不能作为左值的值就是右值,右值不能出现在赋值语句中等号的左侧
结论:
c++一条表达式,要么是右值,要么就是左值。左值有时候当作右值使用。
例如:
int i = 0;
i = i + 1;//i是左值 虽然出现在右边
//i出现在右边 我们说i有右值属性
//一个左值既有左值属性也有右值属性
用到左值的运算符有哪些?
- 赋值表达式
int a = 10;
- 取地址 &
&a;
- string,vector下标[]都需要左值。迭代器。
string abc = "I Love China!";
vector <int>::iterator iter;
iter++;
iter--;
abc[0];
- 其他一些运算符判断是否左值
//i++;
//5++;
//左值表达式就是左值,右值表达式说的就是右值
//左值:代表一个地址,结果是一个对象就是地址
//求值结果为对象的表达式,不代表一定是左值,具体再分析
引用分类
分类
细分为:左值引用、右值引用和const引用
//1.左值引用
int value = 10;
int &refval = value;
refval = 13;// value = 13;
//int &ref;错误必须初始化 引用必须初始化
//int &ref = 1;不能绑定到右值
//2.const引用 常量引用 不能改变值的对象,可以绑定左右值
const int &refval2 = value;
const int &refval22 = 10;
//实际是通过临时变量 绑定到临时变量
//refval2 = 100;错误不能修改
//3.右值引用(绑定到右值)用&&来体现 用于存放一些即将销毁的临时变量
int &&refvalue3 = 3;
refvalue3 = 5;
能绑定到左值上的不能绑定到右值上,反之同理。
string st = "I Love China!";
string &st1 = st;//可以
string &st2 = "I Love China!";//不可以,左值引用不能绑定到临时变量,临时变量被系统当作右值
const string &st3 = "I Love China!";//可以
string &&st4 = st;//不行
int i = 2;
int &r1 = i
int &&r2 = i * 100;//不可以 i*100是一个右值了
总结:
- 返回左值引用的函数,连同赋值,下标和前置递增递减运算符都是返回左值表示式的例子,可以用左值引用
- 返回非引用类型的函数,连同算术,关系,位和侯值递增递减运算符都是右值例子,可以用右值引用
- 但是可以用const引用使用上面的表达式
- 虽然int &&r2中r2是右值引用 ,但是r2本身是左值
- 临时变量都是右值
++i;//左值表达式,返回是i本身地址 先加后用
i++;//右值表达式,先产生临时变量 +1之后再返回临时变量。先用后加
右值引用的目的
- c++11引入 &&代表一种新的数据类型
- 提高程序运行效率,把拷贝对象变成了移动对象来处理提高了运行效率
- 移动的对象如何发生。&&应付移动构造函数和移动赋值运算符
std::move函数
移动 实际上没有做移动操作。只是把一个左值强制转换为右值。
建议执行之后就不要使用第一个变量了。
int tt = 100;
// int &&ttt = tt;//错误
int &&tttt = std::move(tt);
tttt = 10;//tt也为10了;
string st = "I Love China!";
string df = std::move(st);//st为空了,因为string 里的移动构造函数把st的内容移动到了df 而不是std::move的影响 这里的df是新的对象
string &&df1 = std::move(st);//建议这样执行之后就不要使用st了
df1 = "f22f";
string &&df2 = std::move(st);//这里df2和st是同一个意思,st不为空,不会发生string移动构造函数;