当前位置: 首页 > news >正文

移动语义和完美转发

移动语义:把数据从一个对象中转移到另一个对象中,从而避免拷贝操作所带来的性能损耗。
左值引用和右值引用在移动语义的实现中的作用:区分拷贝操作与移动操作。
左值和右值:简单来讲的话,有名字的,可以取地址的就是左值,没有名字的,不能取地址的就是右值。
右值引用是不能绑定到任何左值的,但常量左值例外,常量左值是一个万能引用,可以引用任何值。

bool &&_j = true;
const bool &judge = _j; 可以通过编译

std::move
注意这个函数的名字有点迷惑性,实际上std::move并不能移动任何东西,它唯一的功能是将一个左值强制转化为右值引用,继而可以通过右值引用使用该值,也就是使用移动构造函数或移动赋值函数,以实现移动语义,实现资源所有权的转移(因为a=move(b)的操作其实也是要调用a的构造函数或赋值函数,而move(b)将左值b强制转换为右值之后就会匹配使用移动构造或移动赋值了)。从实现上讲,move基本等同于一个类型转换。
值得注意的是,通过move转化成右值后,被转化的左值的生命周期并没有随着左右值的转化而改变。但通常情况下,我们需要转换成右值引用的还是一个确定生命期即将结束的对象。
NRVO(命名返回值优化):指函数返回一个对象,那么该临时对象的数据所有权会直接转移给调用方,而不是重新构造一个新的对象。详见一文入魂:妈妈再也不担心我不懂C++移动语义了

c++11的移动语义和完美转发
[C++特性]对std::move和std::forward的理解

具体来说可以通过重载构造或者赋值函数的参数是左值引用或右值引用可以来决定是使用拷贝操作还是移动操作。
拷贝操作->使用拷贝构造函数->拷贝构造函数的函数参数是左值引用
移动操作->使用移动构造函数->移动构造函数的函数参数是右值引用

一文入魂:妈妈再也不担心我不懂C++移动语义了

在程序的执行过程中,对于引用的传递实际上会有额外的隐式的转化(如果任一引用为左值引用,则结果为左值引用。否则(即两个都是右值引用),结果为右值引用),一个右值引用参数经过函数的调用转发可能会转化成左值引用,而这就可能会导致不必要的拷贝操作,但这就不是我们希望看到的结果。

而完美转发简单来讲,解决的问题就是在函数参数传递过程的中左值依旧为左值,右值依旧为右值防止隐式转换。主要的应用场景是在模板编程的过程中当进行参数的二次转发,右值会在二次传递中变为左值,而只用std::forward()可以避免这种情况的发生。

以下面代码为例,当调用PrintType()函数,main函数中传入PrintType函数的参数类型为T&&(右值形式),但由于PrintType()函数内部需要进行参数的二次传递,并且右值引用本身是一个左值,因此调用类A的构造函数时会调用拷贝构造函数,而如果使用std::forward()完美转发,就可以解决这个问题。(口语化来讲,就是当一个参数作为右值传入,在需要在函数内部进行二次传参时,由于右值引用本身是一个左值,所以被二次传参后会导致不必要的构造或拷贝,而使用完美转发能避免这一点)

#include <iostream>
#include <algorithm>
#include <windows.h>using namespace std;class A {
public:A() {cout << "调用构造函数" << endl;}A(int& a) {cout << "调用拷贝构造" << endl;}A(int&& a) {cout << "调用移动构造" << endl;}};template<typename T>
void PrintType(T a) {A a1(a);A a2(forward<T>(a));}int main() {SetConsoleOutputCP(CP_UTF8);PrintType(1);return 0;
}// 上面代码输出结果:
// 调用拷贝构造
// 调用移动构造

http://www.mrgr.cn/news/45149.html

相关文章:

  • 容器化技术:Docker的基本概念和使用
  • 全是细节|大模型SFT的100个关键点
  • 【Android】限制TextView大小并允许滑动
  • 【自动驾驶】《Planning-oriented Autonomous Driving》UniAD论文阅读笔记
  • AI绘图创造无限可能,以参考图片为灵感生成图片
  • scrapy 爬取微博(六)【最新超详细解析】:情感分析+保存数据库
  • BeeS CMS 靶场漏洞攻略
  • 33 基于单片机的智能窗帘控制系统
  • 华为OD七日集训第4期 - 按算法分类,由易到难,循序渐进,玩转OD
  • 【大数据应用开发】2023年全国职业院校技能大赛赛题第04套
  • 基于java SpringBoot和Vue校园求职招聘系统设计
  • PHP 表单基础
  • 【人工智能】Transformers之Pipeline(一):音频分类(audio-classification)
  • 如何从数码相机中恢复已删除的照片
  • 机器学习:开启智能时代的钥匙
  • Python网络爬虫从入门到实战
  • Linux 命令 netstat 的 10 个基本用法
  • 机房空调远程控制-Thingsboard MQTT 接口说明
  • 车载音频焦点(二)
  • C++11标准模板(STL)- 常用数学函数 - 计算反正切,以符号确定象限(std::atan2, std::atan2f, std::atan2l)