C++ 左值和右值、移动语义

本文介绍了C++中的左值和右值的概念,指出左值是可持久的对象,右值是临时性的。通过示例代码说明了左值引用和右值引用的区别,强调右值引用能用于移动语义,提高性能。移动语义在std::vector的移动构造中得到体现,避免了深拷贝,显著提升了效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

void fun1(int& var){
	cout<< var << endl;
}
void fun2(int&& var){
	cout<< var << endl;
}

int main(){
int val = 12;
fun1(12); //error
fun1(val);
fun2(2);
}

什么是左值什么是右值?

左值:指表达式结束后依然存在的持久对象
右值:表达式结束就不再存在的临时对象
左值和右值的区别:左值持久,右值短暂

怎么判断左值右值?
在c++中能取地址的就是左值,不能取地址的就是右值。字面量是右值,对于上面的代码来说,字面量12属于右值,val属于左值。右值不能被左值引用所引用右值可以被右值引用所引用

移动语义

移动std::vector,想象一下这个场景。

vector<int> vec_orange = {1, 42, 23, 7, 13};
vector<int> vec_red = vec_orange ;

这样的结果就是,在堆上新创建一块内存,用来存储vec_red 。
在这里插入图片描述

vector<int> vec_orange = {1, 42, 23, 7, 13};
vector<int> vec_red = std::move(vec_orange );

//vec_green.push_back(1);
//vec_green.push_back(2);
//vec_green.push_back(3);
//vec_green.push_back(4);

在这里插入图片描述

可以看到,移动构造vec_red 时,并没有把原来的数组内容复制一遍,而是直接把指针指向orange_vector的数组,然后把orange_vector的指针置空,再设置red_vector的大小为该数组的大小,是否简单明了?这样依赖,无论数组多大,移动构造都只需要设置几个寄存器大小的变量,相比复制构造要去动态分配内存、再递归调用每个元素的复制构造函数的速度快得多,这便是“移动语义提升性能”的一种直观体现。

参考:
知乎-认识C++移动语义与右值引用

### C++的概念及区别 在现代 C++ 编程中,理解 **lvalue()** **rvalue()** 是至关重要的。这一概念不仅影响资源管理技术(如移动语义完美转发),还能够显著提升程序性能。 #### (LValue) 是指具有持久存储地址的对象,可以出现在赋表达式的侧或侧。它通常表示变量名或者可以通过取址运算符 `&` 获取其内存地址的实体。例如: ```cpp int x = 10; int& ref = x; // 变量x是一个 ``` 上述代码中的 `x` 是一个典型的,因为它有固定的内存位置,并且可以在后续计算中被修改[^1]。 #### (RValue) 则是指临时对象或者是不可命名的,它们一般只存在于表达式求的过程中,无法直接获取其地址。通常是常量、函数返回的结果或是匿名对象。例如: ```cpp int y = 20 + 30; // 表达式20+30是 std::string().size(); // 返回的是一个临时字符串大小,也是 ``` 这里需要注意的是,不具备长期存在的特性,在大多数情况下会在当前作用域结束时销毁。 #### 主要差异总结 以下是两者的主要区别列表: - **生命周期**: LValues拥有较长的生命期直到程序运行完毕或超出范围才释放;而RValues生命短暂仅限于单次表达式评估期间有效。 - **可变性**: 大多数时候你可以改变一个lvalue所代表的内容(除非声明为const),但是不能更改由rvalue表示的数据项。 - **能否取地址**: 能够应用取地址操作(&)到lvalues上得到具体物理存储单元的位置信息,但对于真正的rvalues来说这是不可能做到的事情因为它们并没有实际分配固定区域来保存自己。 随着C++标准的发展特别是引入了rvalue reference语法之后(later versions like C++11 onwards), 开发者获得了更多控制权去处理这些不同类型之间的转换关系从而实现更高效地利用计算机硬件资源比如减少不必要的拷贝动作等等. ```cpp // 示例展示如何使用引用以及std::move优化性能 void processLargeData(std::vector<int>&& data){ large_data_member = std::move(data); } processLargeData(createHugeVector()); // 避免深复制,提高效率 ``` 以上例子展示了当调用createHugeVector()产生的巨大向量作为参数传递给function 'processLargeData'的时候不会发生昂贵的deep copy而是采用转移所有权的方式完成任务大大节省时间空间开销.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值