c++11——左值、右值、完美转发、移动语义

发布于:2025-07-12 ⋅ 阅读:(21) ⋅ 点赞:(0)

目录

一、引入左值、右值、完美转发、移动语义的原因

二、左值和右值

(一)左值和右值定义

1.左值

2.右值

3.将亡值

(二)左值引用和右值引用

1.左值引用

2.右值引用

 3.常性引用——万能引用

4.总结

三、右值中的完美转发

(1)引入完美转发的原因

(2)定义

(3)完美转发的实现: 转发引用+std::forward

四、右值中的移动语义

(1)引入移动语义的原因

(2)std::move强制触发移动


一、引入左值、右值、完美转发、移动语义的原因

用于优化对象传递和资源管理。

二、左值和右值

(一)左值和右值定义

1.左值

表达式结束后仍然存在的持久对象,可位于赋值号左侧(有明确内存地址),可以取地址

举例:变量、数组元素、成员变量、函数返回的左值引用等。

2.右值

表达式结束后不再存在的临时对象,只能位于赋值号右侧(无明确内存地址),不可以取地址。

举例: 字面常量、临时对象、不具名的对象、右值引用等。

注意:字面常量纯右值,值不能被改变。

3.将亡值

将亡值:在表达式运行和计算过程中产生的临时量或临时对象,即将被销毁,可被右值引用捕获,会触发移动语义,从而允许资源转移。

不具名就是右值,具名就是左值

注意:内置类型的将亡值不允许赋值,但自定义类型的将亡值可以赋值,可以修改。

(二)左值引用和右值引用

1.左值引用

左值引用是对左值的引用,用&表示。

(1)可以绑定到左值。

(2)const左值引用(常量引用)可以绑定到右值。

(3)左值可以避免拷贝:作为函数参数,传递对象时避免拷贝、修改实参(尤其适用于大对象)。

(4)判断下列哪个可以被正常引用?

int a=10;

&a++;

&++a;

&a++: 不能被正确引用——后置++返回的是一个临时对象,是一个右值,不能引用。

&++a:可以被正确引用——前置++返回的是对象的引用(左值),所以可以引用。

2.右值引用

右值引用是对右值(临时对象或将亡值)的引用,&&表示。

(1)只能绑定到右值

(2)右值引用可以实现移动语义:通过右值引用识别临时对象,直接转移其资源(如堆内存),避免拷贝。

(3)右值引用也可以实现完美转发:在模板中保留参数的原始值类别(左值 / 右值)。

 3.常性引用——万能引用

可以绑定到左值或者右值,但不允许修改引用的对象,只允许只读访问。

4.总结

左值引用:绑定左值,用于避免拷贝,可以修改实参。是 C++98 就有的特性。

右值引用:绑定右值,用于实现移动语义和完美转发,是 C++11 引入的核心特性。

三、右值中的完美转发

(1)引入完美转发的原因

当函数模板将参数传递给其他函数时,无论传入的是左值还是右值,参数都会变成左值(因为参数本身是具名变量)。导致无法根据原始参数的类型选择最优的重载函数

(2)定义

完美转发(Perfect Forwarding) 是一种机制,用于在函数模板保持参数的原始值类别(左值 / 右值)和 const 属性,并将其转发给其他函数。

(3)完美转发的实现: 转发引用+std::forward

①转发引用:是一种特殊机制,允许模板函数根据传入的参数自动推导引用类型。

②std::forward:用于根据T的推导类型,将参数恢复为原始值类别

四、右值中的移动语义

(1)引入移动语义的原因

对象拷贝会复制整个资源(如堆内存、文件句柄),即使源对象是临时的(如函数返回值),但对于马上要销毁的临时对象,复制完全冗余的。

移动语义通过直接转移资源所有权(而非复制),避免了开销,拥有堆资源或者内核资源就需要使用移动语义。

(2)std::move强制触发移动

将左值转化为右值引用,但无法移除const属性。


网站公告

今日签到

点亮在社区的每一天
去签到