首页 > 编程语言 >C++11中的:移动语义(std::move)、完美转发(std::forward)、std::ref和std::cref

C++11中的:移动语义(std::move)、完美转发(std::forward)、std::ref和std::cref

时间:2023-03-16 15:35:04浏览次数:51  
标签:std 11 右值 move 左值 Test array

左值(lvalue)与右值(rvalue)

左值与右值的概念其实在C++0x中就有了。概括的讲,凡是能够取地址的可以称之为左值,反之称之为右值,C++中并没有对左值和右值给出明确的定义,从其解决手段来看类似上面的定义,当然我们还可以定义为:有名字的对象为左值,没有名字的对象为右值。

 
  class A   {};   1   2   A a; // a为左值,因为其有明确名字,且对a进行 &a 是合法的。       void Test(A a)   {   __Test(a);   }       Test(A()); // A() 为右值,因为A()产生一个临时对象,临时对象没有名字且无法进行 &取址操作。       对 __Test(a); 而言,这里的a为左值,因为这里的a对调用方而言是具名的,   __Test内部对a也是可以进行 &取址操作的。   但这个a在调用完毕后很快被销毁,毕竟它只是一个临时变量。       所以从上述的伪代码中还可以知道:因为函数内的嵌套调用,   上一层的右值是可以“变成”左值以完成下层调用,意即:可以接受右值的右值引用本身却是个左值
 
 

(https://blog.csdn.net/hejjunlin/article/details/78104719)

 

移动语义(std::move)

 在C++11中,标准库在<utility>中提供了一个有用的函数std::move,std::move并不移动任何对象与数据,它的功能是将一个左值或者右值强制转化为右值引用,std::move基本等同于一个类型转换:static_cast<T&&>(lvalue)。

td::move解决效率问题,减少不必要的拷贝:A对象可以根据右值引用知道传入的是一个临时的对象B,把临时对象B中的堆内存数据(可能是大数据块)直接使用而不重新分配内存,再把临时对象B对应指针置空,实现数据移动(move之后B对象不能再使用)。减少了A重新分配内存与数据拷贝的消耗以及临时对象B进行数据销毁的消耗。

 
  class Test   {   public:   Test() :array(nullptr)   {   }       ~Test()   {   if(nullptr != array)   {   delete [] array;   array = nullptr;   }   }       Test(Test &&other)   {   this->array = other.array;   other.array = nullptr;   }       Test& operator = (Test &&other)   {   //do some operate...   this->array = other.array;   other.array = nullptr;   return *this;   }       private:   int *array;//指向一个很大的数组   };           Test B;   //do some thing to B.array   Test A(std::move(B));
 
 

完美转发(std::forward)

当我们将一个右值引用传入函数时,他在实参中有了命名,所以继续往下传或者调用其他函数时,根据C++ 标准的定义,这个参数变成了一个左值。那么他永远不会调用接下来函数的右值版本,这可能在一些情况下造成拷贝。为了解决这个问题 C++ 11引入了完美转发,根据右值判断的推倒,调用forward 传出的值,若原来是一个右值,那么他转出来就是一个右值,否则为一个左值。
这样的处理就完美的转发了原有参数的左右值属性,不会造成一些不必要的拷贝。

 
  #include <iostream>   #include <vector>   #include <string>       using namespace std;       int main()   {   string A("abc");   string&& Rval = std::move(A);   string B(Rval); // this is a copy , not move.   cout << A << endl; // output "abc"   string C(std::forward<string>(Rval)); // move.   cout << A << endl; /* output "" */   return 0;   }
 
 

(https://blog.csdn.net/coolwriter/article/details/80970718)

 

std::ref和std::cref

https://blog.csdn.net/lmb1612977696/article/details/81543802

 

 

标签:std,11,右值,move,左值,Test,array
From: https://www.cnblogs.com/lidabo/p/17222748.html

相关文章

  • PG从小白到专家 - Part 11:PostgreSQL控制文件作用与管理
     PostgreSQL从小白到专家,是从入门逐渐能力提升的一个系列教程,内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容,希望对热爱PG、学习PG的同......
  • 旧电脑或者没有TPM的电脑上安装win11
    一般安装win11都需要开启TPM模块,一般在主板上直接打开就好了,但是很多旧电脑遇到不符合Win11最低要求,这是因为有些比较旧的华硕主板,没有TPM或不支持TPM2.0Win11系统最低配......
  • Wallys|DR4019S|IPQ4019|Support 11ABGN/802.11AC
     Ifyou'reinthemarketforahigh-performanceWi-Fisolutionforyourbusinessorhome,looknofurtherthantheQualcommIPQ4019.Thiscutting-edgesyste......
  • Remove First and Last Character
    InstructionsIt'sprettystraightforward.Yourgoalistocreateafunctionthatremovesthefirstandlastcharactersofastring.You'regivenoneparameter,......
  • 11个步骤排查主机是否被入侵
    11个步骤完美排查linux机器是否已经被入侵入门小站 入门小站 2023-03-1321:50 发表于湖北入门小站分享运维技巧及10k+Stars的开源项目225篇原创内容......
  • 路飞项目day11
    上节回顾#1课程相关数据录入-simpleui中录入-使用sql录入,在media下图片copy过去#2课程分类接口#3查询所有课程接口-带排序:人气,价格......
  • 11.扫描(即扫略、管道-圆形轮廓+薄壁)
    一、简单扫描1.点击进入草图-样条曲线绘制,点击完成2.创建与样条曲线垂直的基准平面 3.汇总扫描截面,设置几何约束-穿透 4.点击扫描,选择引导线和截面,点击确认即可......
  • stdarg.h
    //定义char*指针类型#defineva_listchar*va_listap;char*ap;//指向可变参数的第一个#defineva_start(ap,last_arg)(ap=(va_list)&last_arg+sizeof(last......
  • 关于shutil.move
    导师有个需求,要移动文件使用shutil库,看网上说的shutil.move的描述,结果都是错的真正的,shutil.move第二个参数的文件夹不存在时,会把它当成一个目标文件而重复覆盖。只有当......
  • 2203031110 黄正淳
    #include<stdio.h>intmain(){inta,b,temp;scanf("%d%d",&a,&b);temp=a;a=b;b=temp;printf("%d%d",a,b);return0;}#include<stdio.h>intmain(......