左值 右值 std::move函数

左值

左值的概念

左值是一个内存块的表达,,代表一个地址,可以被取地址,赋值, 常常出现在赋值语句的左边.变量, 数组元素, 结构成员, 引用, 和解除引用都是左值.

左值常用的运算符

赋值运算符:

int a;
printf("%d",  a = 4);

 此处的a是一个左值, 当把4写入内存后, 整个表达式结果还是左值

(a = 4) = 5;

 数组元素[]:

int arr[3] = {3, 5, 6};

 arr[0]是一个左值, arr[0]可以被修改,写入

引用和解除引用的指针都是左值

vector<int>::iterator iter;
iter++, iter--

 右值

右值的概念:

右值是不能通过地址访问的值,且右值不可被取地址, 这些值常常在寄存器上

常见的右值

"abc" 右值
16 右值
x + y 这种表达式是右值
常规函数的返回值也是右值

 右值不可以写入

x + y = 3; // no
"abc" = "ghj"; // no;
10 = n; // no

 引用的分类

左值引用 

左值引用是是对左值进行引用的类别, 使用&符号进行声明, 它可以绑定一个左值.不可以引用右值

int a = 10; // a 是一个左值
int & value = a; // 左值引用
int & val = 100; // 不允许绑定右值

右值引用 

 右值引用是对右值进行引用的类型, 使用&&符号声明, 他可以绑定一个右值, 但不能绑定左值.

int && ref = 100; // 右值引用.
int a = 100;
int && value = 100; // 不允许绑定左值

const引用 

const引用是对常量对象的引用, 使用const关键字进行声明, 可以绑定左值或右值,但不能修改所引用的对象.

int a = 100;
const int & value_1 = 100;
const int & value_2 = a;

 const之所以可以绑定右值,是因为会生成临时对像

const int & a = 100;
这条语句等同于
int && temp = 100; // 先生成一个右值引用
const int & a = temp; // const引用绑定到右值

 案例分析

++i, i++

++i, // 左值表达式, ++i先给变量加1, 然后返回本身, 所以是一个左值
(++i) = 5; // 可以被赋值

i++, // 先生成一个临时对象, 记录i的值, 之后在给i加1, 返回这个临时变量, 所以是一个右值
(i++) = 5; // 不可以被赋值

 右值引用本身是左值

int && ref = 100; // 右值引用
int & value = ref // 左值引用
int && ref_2 = ref // 不可以将左值绑定到右值引用

 对左值引用的修改, 会改变原来内存块的值, 右值引用则不会改变

int a = 100;
int & ref_2 = ++a;
ref_2 = 101; // 对ref_2的修改, 会导致变量a的改变

int && ref_2 = a++;
ref_2 = 101; // ref_2和a已经没有任何联系, 修改ref_2的值与a没有任何关系

 重点强调

(1), 右值引用虽然引用了右值, 但其本身是一个左值

(2), 所有的变量都是一个左值, 因为他们有地址, 而且右值引用也无法绑定

(3), 任何函数形参都是左值, void func(int a, int && b) 虽然b是右值引用, 但是本身是一个左值

(4), 临时对象都是右值.

 右值引用的引入目的

C++11引入右值引用的目的是为了支持移动语义和完美转发.

std::move()函数

std::move函数能够将一个左值强制转换成右值, 带来的结果就是可以将其绑定到右值上去.

int i = 10;
int && ref = std::move(i); // 将i转变成一个右值, 实现右值引用

ref = 20;
cout << ref << " " << i << endl; // 输出20 20

i = 29;
cout << ref << " " << i << endl; // 输出29 29

当将i绑定到ref后, 对ref的改变, 或者是对i的改变都会影响彼此.

int && ref_1 = 100;
int && ref_2 = std::move(ref_1); // 此时, ref_1 = 100, ref_2 = 100;

ref_1 = 200; // 此时, ref_1 = 200, ref_2 = 200;
ref_2 = 300; // 此时, ref_2 = 300, ref_1 = 300;

 注意: std::move()函数没有移动功能.在移动完后,应该避免对源对象的使用.(就像上面的例子中, 使用了ref_1后,应该避免以后再次使用).

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值