[C++] C++11新特性之左值右值、左值引用右值引用、mov、forward
2021/8/6 14:36:01
本文主要是介绍[C++] C++11新特性之左值右值、左值引用右值引用、mov、forward,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
参考
- C++ Primer
- C++ 11 左值,右值,左值引用,右值引用,std::move, std::foward
左值右值
C++的表达式要么是左值,要么是右值。
简单说,左值可以位于赋值语句的左边,右值则不能。
- 右值:当一个对象被用作右值的时候,用的是对象的值(内容),右值要么是字面常量,要么在表达式求值过程中创建的临时对象,没有名字,不能被赋值。
- 左值:当一个对象被用作左值的时候,用的是对象的身份(在内存中的位置),左值就是有名字的对象,可以被赋值,左值可以被取地址,左值持久
- 需要右值的地方可以用左值来代替,不能把右值当成左值使用,当左值当成右值使用的时候,实际上使用的是它的内容(值)
需要用到左值:
- 赋值运算符需要一个(非常量)左值作为其左侧运算对象,得到的结果仍然是一个左值
- 取地址符作用于一个左值运算对象,返回指向该运算对象的指针,这个指针是一个右值
- 内置解引用运算符、下标运算符、迭代器解引用运算符、string和vector的下标运算符求值结果都是左值
- 内置类型和迭代器的递增递减运算符作用于左值运算对象,前置版本作用的和得到的都是左值
左值引用右值引用
#include <iostream> //函数重载,形参为左值引用,接受左值 void process_value(int& i) { std::cout << "LValue processed: " << i << std::endl; } //函数重载,形参为右值引用,接受右值 void process_value(int&& i) { std::cout << "RValue processed: " << i << std::endl; } int main() { int a = 0; process_value(a);//传入左值,输出:LValue processed: 0 process_value(1);//传入右值,输出1:RValue processed: 1 }
-
左值引用&:不能将一个左值引用绑定到要求转换的表达式、字面常量或者返回右值的表达式
-
右值引用&&:某个对象的另一个名字,可以将一个右值引用绑定到要求转换的表达式、字面常量或者返回右值的表达式,不能将右值引用直接绑定到一个左值上,右值引用指向将要被销毁的对象,用右值引用接管所引用的对象的资源
int i = 1; int &&p = i;//错误,不能将一个右值引用绑定到一个左值上 int &q = i * 22;//错误,不能将左值引用绑定到返回右值的表达式,i * 22是一个右值 int &&q2 = i * 22;//正确,右值引用可以绑定到乘法右值结果上
-
可以把左值引用绑定到返回左值的表达式(返回左值引用的函数、赋值、下标、解引用、前置递增递减运算符)
int i = 1; int &r = i;//正确,左值引用
-
可以把const左值引用或者右值引用绑定到返回右值的表达式(返回非引用类型的函数、算术、关系、位、后置递增递减运算符)
const int &q1 = i * 22;//正确,可以将const引用绑定到右值
-
p是右值引用,指向一个右值,p本身是左值
include <iostream> //函数重载,形参为左值引用,接受左值 void process_value(int& i) { std::cout << "LValue processed: " << i << std::endl; } //函数重载,形参为右值引用,接受右值 void process_value(int&& i) { std::cout << "RValue processed: " << std::endl; } int main() { int a = 0; process_value(a);//输出:LValue processed: 0,说明传入的是左值 int&& p = 3; process_value(p); //输出:LValue processed: 3,说明传入的是左值 } //以上例子说明p是右值引用,指向一个右值,p本身是左值
不能将一个右值引用绑定到一个右值引用类型的变量上
变量是左值,不能将一个右值引用直接绑定到一个变量上
int &&p = 11;//正确,字面常量是右值 int &&q = p;//错误,p是左值
-
右值引用的意义
-
为临时变量续命,也就是为右值续命,因为右值在表达式结束后就消亡了,如果想继续使用右值,那就会动用昂贵的拷贝构造函数。
-
右值引用是用来支持转移语义的。转移语义可以将资源 ( 堆,系统对象等 ) 从一个对象转移到另一个对象,这样能够减少不必要的临时对象的创建、拷贝以及销毁,能够大幅度提高 C++ 的性能。
-
转移语义是和拷贝语义相对的,可以类比文件的剪切与拷贝,当我们将文件从一个目录拷贝到另一个目录时,速度比剪切慢很多。
-
C++11 之move函数
头文件utility
使用move函数将获得一个绑定到左值上的右值引用类型
int &&p = 11;//正确,字面常量是右值 int &&q = p;//错误,p是左值 int &&q = std::move(p);//正确,move返回给定对象的右值引用
对于move不提供using声明,必须写成std::move,不能写成move
C++11 之forward
头文件utility
与move不同,forward必须通过显式模板实参来调用
forward返回该显式实参类型的右值引用,即forward返回的是T&&
template <typename F, typename T1, typename T2> void flip(F f, T1 &&t1, T2 &&t2) { f(std::forward<T2>(t2), std::forward<T1>(t1)); } //如果调用flip(g, i, 42),i将以int&类型传递给g,42将以int&&类型传递给g
这篇关于[C++] C++11新特性之左值右值、左值引用右值引用、mov、forward的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-26怎么使用nsenter命令进入容器?-icode9专业技术文章分享
- 2024-12-26导入文件提示存在乱码,请确定使用的是UTF-8编码怎么解决?-icode9专业技术文章分享
- 2024-12-26csv文件怎么设置编码?-icode9专业技术文章分享
- 2024-12-25TypeScript基础知识详解
- 2024-12-25安卓NDK 是什么?-icode9专业技术文章分享
- 2024-12-25caddy 可以定义日志到 文件吗?-icode9专业技术文章分享
- 2024-12-25wordfence如何设置密码规则?-icode9专业技术文章分享
- 2024-12-25有哪些方法可以实现 DLL 文件路径的管理?-icode9专业技术文章分享
- 2024-12-25错误信息 "At least one element in the source array could not be cast down to the destination array-icode9专业技术文章分享
- 2024-12-25'flutter' 不是内部或外部命令,也不是可运行的程序 或批处理文件。错误信息提示什么意思?-icode9专业技术文章分享