打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
UC头条:[C ]右值引用(极详细版)
userphoto

2023.06.29 山西

关注

当构造传左值,就走拷贝构造,当构造传右值,就走移动构造。

对于左值,我们后续还要使用,所以只能进行深拷贝,完成拷贝构造。

但对于右值(将亡值),可以直接进行资源的交换,将this和将亡值交换资源。

所以,回到函数传返回值的问题:

点击加载图片

在有了移动构造以后,再经过编译器的优化,就可以做到直接移动构造(资源的交换),实现0拷贝,效率极高!!

2.移动赋值

第一种情况是针对拷贝构造的情况,接下来是针对赋值拷贝的情况:

赋值拷贝同理可得:

点击加载图片

这里运行后,我们看到调用了一次移动构造和一次移动赋值。

因为如果是用一个已经存在的对象接收,编译器就没办法优化了。mj::to_string函数中会先用str生成构造生成一个临时对象,但是我们可以看到,编译器很聪明的在这里把str识别成了右值,调用了移动构造。然后在把这个临时对象做为mj::to_string函数调用的返回值赋值给ret,这里调用的移动赋值。(直接资源交换)

点击加载图片

总结:

点击加载图片

点击加载图片

2.对于插入右值数据时,也可以减少拷贝

只有左值引用时的插入接口:

点击加载图片

入接口函数也增加了右值引用版本:

会直接进行资源交换,将将亡值和新创建的节点中的数据进行资源交换。

4.万能引用和完美转发

讲到这里,我们埋的伏笔也就要出来了:有左值引用,const左值引用;右值引用,但却没有提到const右值引用。

需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可

以取到该位置的地址。(右值被右值引用以后就成为了左值)

例如:不能取字面量10的地址,但是rr1引用后,可以对rr1取地址,也可以修改rr1。如果不想rr1被修改,可以用constint&&rr1去引用。

intmain{doublex=1.1,y=2.2;int&&rr1=10;constdouble&&rr2=x+y;rr1++;//rr2++;//不可以修改cout<<&rr1<<><>< p=''><><><><>

当然这个的具体应用场景在这里:

例如:

点击加载图片

这里的移动构造和赋值构造,如果参数设为右值引用,那么作为右值如果不可以被修改,那资源的交换就不可以进行,所以这就是为什么,右值引用右值以后,就成为了左值。

情况二:

在我们自己模拟实现的list中,也实现插入接口是右值引用:

点击加载图片

这就是在传右值时,右值引用会改变右值的特性,将其变为左值,那么需要不断move(左值)。

所以我们会想,有没有这么一个东西,自动去识别我们传的参数是左值还是右值,不会因为右值引用而改变右值属性。我们继续往下看

1.万能引用

当并不明确规定传右值或者左值时:

点击加载图片

万能引用在这里起到了用处,可以随便传。(也叫做折叠)模板中的&&不是右值引用,而是为了万能引用,可以折叠。当传左值时,就把两个&&折叠为一个。同理可得

但是在继续调用Fun时,还是会因为属性导致结果并不是我们需要的:

点击加载图片

走到调用fun(t)时,还是会因为右值引用导致右值变为左值,所以又出来了完美转发:

templatevoidPerfectForward(T&&t){//t可能是左值,可能是右值//Fun(move(t));//完美转发,保持他属性Fun(std::forward(t));//t++;}

很好的保持了属性。

所以在这里:

点击加载图片

点击加载图片

总结

右值引用的两个价值;

万能引用和完美转发

我们下期再见!

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C++构造函数和析构函数
右值引用
const与#define的优缺点?
C++拷贝构造函数详解(转)
C 拷贝构造函数详解
C++中内存泄漏的几种情况
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服