C++左值右值和移动语义

来源:互联网 发布:数据新闻报道方向 编辑:程序博客网 时间:2024/05/20 13:37

最近看了很多相关博客,自己总结一下,单纯根据在等号左边还是右边明显判断太过粗糙,我的大致理解如下:
判断object是左值还是右值(三种方法):
(1)object能否被取地址,即&object是否合法;
(2)object能否被赋值,即object=other_object是否合法;
(3)object在当前语句执行完就销毁还是会继续存在,即临时对象还是持久对象;
然后是左值引用和右值引用,其实两者就是指引用,只是左值引用引用的是左值,右值引用引用的是右值。为了更进一步解释,我们看看下面的例子:

int add(int a, int b){    return a + b;}cout << add(2, 3);

这是最简单的版本,我们没有使用任何引用,但是这会导致函数调用和返回过程中造成多次拷贝消耗,浪费计算资源,接下来看看左值引用:

int& add(int a, int b){    return a + b;}cout << add(2, 3);

这里期待的返回值是左值引用,但是函数内返回的是(a+b),根据开始的判断方法,这是一个右值,没法赋值给一个左值引用(vs2013提示“非常量引用的初始值必须为左值”),既然是强调非常量引用,而我又不想把(a+b)赋值给一个变量然后再返回该变量(太麻烦),那就修改为期待返回一个常量左值引用吧,修改如下:

const int & add(int a, int b){    return a + b;}cout << add(2, 3);

那再改改呢?如下:

const int & add(int& a, int& b){    return a + b;}cout << add(2, 3);

这样函数定义是没错,但是调用却会出现问题,因为期待的传入参数是左值引用,而我却传入2和3这样的右值,这里有两种方法:
(1)将形参改为常左值引用:

const int & add(const int& a,const int& b){    return a + b;}cout << add(2, 3);

(2)将右值实参转换为左值再传进函数:

int x=2,y=3;const int & add( int& a, int& b){    return a + b;}cout << add(x, y);

接下来看看右值引用版本:

int && add(int a, int b){    return a + b;}cout << add(x, y);

这是没有问题的,但是如果改成下面的情况:

int && add(int a, int b){    int sum= a + b;    return sum;}cout << add(x, y);

VS2013提示无法将右值引用绑定到左值,那么就把左值转换为右值:

int && add(int a, int b){    int sum= a + b;    return std::move(sum);}cout << add(x, y);

到这里,例子说的已经可以啦,总结一下就是:
(1)值传递时没有太多考虑,就是效率低点,不会影响编译正确性;
(2)右值引用只能绑定到右值;
(3)左值引用只能绑定到左值;
(4)常左值引用可以绑定到右值;
(5)右值赋给一个变量后即可表示为左值;
(6)使用std::move()可以将左值转换为右值;
好的,使用以上知识 大致可以避免左右值引用产生的编译错误了,这是我的理解。

原创粉丝点击