提出问题:在进行vector的封装时,突然疑惑,为什么右值引用的形参,却是一个左值,而且还要把再次它转换成右值才能作为右值使用,此前写移动构造也使用右值引用,但没有对右值引用调用move()函数的操作,对右值引用调用move()函数变为右值,这听起来就很奇怪
先参考https://qa.1r1g.com/sf/ask/4486225411/
左右值是变量的类别,而左右值引用是变量的类型!
可以类比:333是一个右值,你不能说333是一种数据类型,int &&a,a是一个整型的右值引用类型,而右值引用类型就是一个左值
左值:内存
右值:临时值
左值引用:对左值引用
右值引用以及移动构造:
1.将右值直接转换为左值,在C++里,通常产生了右值以后,必须将右值拷贝到一个左值才能保存,但这个拷贝如果是面对大型容器多次拷贝,会产生大量的资源损耗,而直接将右值转换为左值,则节省这些损耗,此时,将右值转换为左值的操作成为移动构造
2.函数重载作为参数只会匹配右值
思路心得:
先说右值引用的真正意义,在此之前还得看一块汇编码
写出test(int a); test(int &a); test(int &&a);
三个函数完全相同且变量a都有参与函数内部操作,
从汇编代码上来看,这三个函数实现没有任何区别,这意味着,三个a都是左值
那么区别在哪里,在调用时,三个test会匹配不同的参数,
而第三个右值引用作为参数的test只会匹配右值的调用,
然而这个右值对int &&a初始化以后,a却变成了左值,那么这和第二个test的操作没有区别,函数内部完全一样,都是对一个新构造的局部变量a进行操作,那么这个意义在哪里呢?!
意义就在于调用test的右值即将析构,右值也可以理解为临时量,只存活于一条语句内,语句结束即销毁
那么就可以放心大胆地对这个即将销毁的数据进行操作,不用担心对这个变量操作会对程序整体产生什么影响,所以在移动构造中我们才可以直接将它的数据成员全部置空,
相反,如果是一个左值,那代表这个变量在程序中占据了一块内存或者起着某些作用,我们就不能肆意地对它进行移动构造,掠夺它的成员,销毁它自身
所以右值引用可以保证我们匹配的一定是一个右值,才可以在函数中对这个右值进行掠夺性的操作
才有了提问中的代码,可以对这个传入的右值引用类型的变量,直接进行move()显式转换为右值,然后进行移动构造这种掠夺性的操作
总结:右值引用起到了匹配右值并将右值转成左值的操作,这样就可以不用担心对某些重要的左值进行误操,保证匹配的都是些即将销毁的右值