本文主要是介绍右值,右值引用,move,forward,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
-
区分左值和右值
一个最为典型的判别方法就是,在赋值表达式中,出现在等号左边的就是“左值”,而在等号右边的,则称为“右值”。
还有一个说法,就是可以取地址的、有名字的就是左传,反之,不能取地址的、没有名字的就是右值。
右值又分将亡值(xvalue),纯右值。
-
引用
引用类型本身自己并不拥有所绑定对象的内存,只是该对象的一个别名。
-
右值引用
右值引用标记为T&&
用右值引用变量声明,会少一次对象的构造及一次对象的析构。
好处:减少内存拷贝,避免无谓的复制,提高程序性能。
左值引用是具名变量值的别名,而右值引用则是不具名(匿名)变量的别名。
总结:
(1)左值和右值是独立于它们的类型,右值引用类型可能是左值也可能是右值
(2)auto&&或函数参数类型的自动推导的T&&是一个未定的引用类型,它可能是左值引用,也可能是右值引用,取决于初始化的值类型
(3)所有的右值引用叠加到右值引用上仍然是一个右值引用,其它引用叠加都为坐值引用,当T&&为模版参数时,输入左值,它会变为左值引用,输入右值则变为具名的右值引用
(4)编译器会将已命名的右值引用视为左值,而将未命名的右值视为右值
-
move
移动语义是通过右值引用来匹配临时值的
有些左值是局部变量,生命周期也很短,能不能也移动而不是拷贝呢?
C++11提供了std::move()方法来将左值转换为右值,从而方便应用移动语义。
move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转义,没有内存拷贝。
MyString str1 = "hello";
MyString str2(str1);
MyString str3 = Fun();
MyString str4 = move(str2);
注:
- 如果我们没有提供移动构造函数,只提供了拷贝构造函数,
std::move()
会失效但是不会发生错误,因为编译器找不到移动构造函数就去寻找拷贝构造函数,也这是拷贝构造函数的参数是const T&
常量左值引用的原因! c++11中
的所有容器都实现了move
语义,move
只是转移了资源的控制权,本质上是将左值强制转化为右值使用,以用于移动拷贝或赋值,避免对含有资源的对象发生无谓的拷贝。move
对于拥有如内存、文件句柄等资源的成员的对象有效,如果是一些基本类型,如int和char[10]数组等,如果使用move,仍会发生拷贝(因为没有对应的移动构造函数),所以说move
对含有资源的对象说更有意义。
-
forward
所谓转发,就是通过一个函数将参数继续转交给另一个函数进行处理,原参数可能是右值,可能是左值,并且保持参数的原有特征。
MyString str1 = "hello";
MyString str2(str1);
MyString str3 = Fun();
MyString str4 = move(str2);
MyString str5(forward<MyString>(str3));
这篇关于右值,右值引用,move,forward的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!