左值引用和右值引用、move函数

    技术2022-07-12  95

    左值是可以放在赋值号左边可以被赋值的值;左值必须要在内存中有实体;右值当在赋值号右边取出值赋给其他变量的值;右值可以在内存也可以在CPU寄存器。一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址。

    左值

    左值:既可以放在等号左侧,也可以放在等号右侧的变量。例如下面的例子:

    int a = 1;

    int& b = a

    上面的变量a既可以放在等号的左侧也可以放在等号的右侧,所以她是左值。

    右值

    右值:只可以放在等号右侧的变量。例如下面的例子:

    int a = 1; int b = a + 2; int& c = a + 2; //error a+2 = 3; // error

    这里的a+2只能放在等好的右侧,所以a+2是右值。

    为什么a+2只能放在等号右侧呢?原因在于a+2会产生一个临时变量,b=a+2实际上是先算出a+2的结果存储到临时变量然后赋值给b,并销毁这个临时变量。如果将a+2放到等好的左侧,那么将产生无意义的结果。

    综合上面的左值和右值的概念我们可以得到“左值持久,右值短暂”的概念。左值持久存在,右值将在运算结束后销毁。

    引用

    引用是C++语法做的优化,引用的本质还是靠指针来实现的。引用相当于变量的别名。引用可以改变指针的指向,还可以改变指针所指向的值。引用的基本规则:声明引用的时候必须初始化,且一旦绑定,不可把引用绑定到其他对象;即引用必须初始化,不能对引用重定义;对引用的一切操作,就相当于对原对象的操作。

    左值引用

    左值引用的基本语法:type &引用名 = 左值表达式;

    右值引用

    必须绑定到右值,一个将要销毁的对象

    右值引用的基本语法type &&引用名 = 右值表达式;

    右值引用在企业开发人员在代码优化方面会经常用到;

    右值引用的“&&”中间不可以有空格。

    右值引用的一个重要性质和作用就是只能绑定到一个将要销毁的对象,因此我们可以将右值引用的资源移动到另一个对象中

    move

    std::move 会无条件将自己的参数转换为右值。在对象拷贝的时候,在运行时,它们不会产生一行代码, 可以减少资源创建和释放。

    浅析C++11右值引用和move语义https://www.k2zone.cn/?p=1880

    我们通常见到的引用(int &a=b;)可以称之为左值引用,而右值引用则是int &&a的形式。右值引用的一个重要性质和作用就是只能绑定到一个将要销毁的对象,因此我们可以将右值引用的资源移动到另一个对象中。

    从上面的介绍我们可以总结出,只有右值可以绑定到右值引用上。但是,话不能说的太慢。我们总有办法能将左值也绑定到右值引用上,我们可以显式的使用move将一个左值转换为对用的右值引用类型。如下:

    int a = 1; int&& b = std::move(a);

    此时,a和b的地址是相同的,b将是a的应用。

    总结出来move的概念其实很简单,就一句话:将一个左值转换为对应的右值引用类型。

    这里需要注意一点的就是,右值引用的是将要销毁的对象,使用move调用意味着告诉编译器我们有一个左值,但想像右值一样使用,所以调用move后原来的对象除了赋值和销毁它外不能有其他的操作(书上是这么说的,但是测试的时候未发现问题)。

    string st = "I love xing"; vector<string> vc ; vc.push_back(move(st)); cout<<vc[0]<<endl; if(!st.empty()) cout<<st<<endl; //输出一行I love xing //原来的字符串st已经为空 string st = "I love xing"; vector<string> vc ; vc.push_back(st); cout<<vc[0]<<endl; if(!st.empty()) cout<<st<<endl; //输出两行I love xing

     

    Processed: 0.009, SQL: 9