- 我最近开了几个专栏,诚信互三!
====> |||《算法专栏》::刷题教程来自网站《代码随想录》。|||
====> |||《C++专栏》::记录我学习C++的经历,看完你一定会有收获。|||
====> |||《Linux专栏》::记录我学习Linux的经历,看完你一定会有收获。|||
====> |||《C#专栏》::记录我复习C#的经历,深度理解,查漏补缺,不定期更新。|||
====> |||《计算机网络专栏》::记录我学习计算机网络,看完你一定会有收获。|||
C++引用和右值引用
- 引用的意义
- 右值引用的移动语义
- 右值引用的属性
- C++11新特性万能引用
引用的意义
引用是C++的特性,在C++11后,又新增了右值引用,引用的存在是很有必要的,引用主要解决的问题如下。
函数传参问题。
返回值的拷贝问题。
引用已经解决了传参问题和部分返回值拷贝问题,但是还有一部分没有解决,于是C++11就新增了右值引用来解决剩余的部分。
右值引用的移动语义
引用解决了返回值的声明周期大于函数的声明周期的拷贝问题,右值引用解决了返回值的声明周期与函数的声明周期相同的拷贝问题。
但是右值引用不是直接解决该问题,而是通过右值引用的移动语义来解决这个问题,在C++11后,新增了更多的默认成员函数,如移动构造,移动赋值等等。
在这种情况下,t1作为临时变量,出作用域就会消失,此时将其通过move转换为右值,然后返回,则会调用移动构造函数,直接将该临时变量的内容交换到新的变量,减少了对象在构造时的时间开销,当然移动构造对深拷贝对象有很好的降低时间复杂度的效果。
在C++11后,STL接口中很多都增加了右值引用版本。
新的默认成员函数,移动构造,移动赋值等,它们会收到如析构函数,拷贝构造,赋值等函数,如果显示写了上面的函数,则默认的移动构造,移动赋值都不会生成。
右值引用的属性
引用的属性是左值,很多人认为右值引用的属性是右值,但这是错的,右值引用虽然引用右值,但是其属性确实左值。
所以在我们进行函数传参是,参数接收一个右值引用,在函数内若使用该参数,则该参数会被解释为左值,本来用户想调用右值函数,但是实际上调用的确实左值函数,为了解决该问题有以下两个方法。
1.增加move将左值转换为右值。
2.使用完美转发。
完美转发是一个C++11提供的接口,可以实现该值穿进来是什么值,使用的时候就是什么值。
右值引用的属性是左值,那么左值引用能否引用右值呢?
const 左值引用可以引用右值,在没有右值引用前,若一个左值函数要接收一个右值,则需要加入const。
右值引用也可以引用左值,move将左值转换为右值。
C++11新特性万能引用
万能引用是一个模板,该模板接收不论右值,还是左值,还是const左值,还是const右值,都可以传入该模板中,让其生成函数。
万能引用模板如上,如果传入右值,则T&& 被解读为 T&&,如果传入左值,则T&& 被解读为 T& ,const同理。
万能引用的出现让模板的可复用性增加了,减少了程序员的代码量,但是可读性变差了。