C++ | 右值引用与std::move()
时间:2023-08-04 05:49:38来源:博客园

右值引用

  • 左值:可以被取地址的变量或值


    (相关资料图)

  • 右值:无法被修改,无法取地址的值。一般为临时变量。

  • 左值引用:

    • 常引用,只能指向左值

    • 或者通过 const的方式指向一个右值

      const int & a = 17;

      所以,函数形参定义为const type & var时,既可以接受变量,也可以接受右值。如std::vectorpush_back()

      void push_back(const type & val);

      如果没有const,那v.push_back(17)这样的代码就无法编译通过了。

  • 右值引用: 只能指向右值的引用,指向左值则无法通过编译

    • 使用右值引用,本质上将一个右值变成了一个左值:int &&a = 17;

      变量a是一个左值,所以右值引用是一个左值

    • 对于函数形参而言,定义为type && var将只接受为右值的实参。

    为什么会有右值引用的出现呢?
    // 类Obj数据的定义class Obj{    int _size;    char *_buf;};

    当我们定义Obj类的构造函数时,如果我们想用对象a来初始化对象b,有时候初始化后我们还想要继续使用对象a,那这时候的构造函数就需要将对象a的数据完全复制给对象b

    Obj(const Obj &o){    _size = o._size;    _buf = new char[_size];    for(int i=0;i<_size;i++) _buf[i] = o._buf[i];}
    (这样称为深拷贝。浅拷贝是简单地复制值,包括指针,经过浅拷贝之后的两个指针只是指向了同一个地址;而深拷贝会在堆内存中另外申请空间给新指针或者新引用)

    而有的时候对象a只是一个临时变量(右值),用完即弃。这时候直接将对象a的数据移动给对象b即可:

    Obj(const Obj &o){    _size = o._size;    _buf =  o._buf;    o._buf = nullptr;}
    (注意到,在移动构造函数中,末尾有o._buf = nullptr。之所以要将被移动数据的对象中的指针/引用置为空指针,原因是避免在对象a和对象b的析构函数中都对该地址进行delete

    但实际上,以上的移动构造函数是无法实现的,因为const使得传入对象无法被修改。因此,为了实现移动构造函数,C++11引入了右值引用:

    Obj(Obj && o){    _size = o._size;    _buf =  o._buf;    o._buf = nullptr;}

    这样问题就得到解决了。当构造函数时传入参数为右值时,会调用Obj(Obj && o);若是左值,则会调用Obj(const Obj & o)

    此时,又有另外一个问题,如果使用一个对象a是一个对象而非一个临时变量,但我依旧想要使用移动数据的方式来构造函数(对象a在之后不再使用),那该怎么办呢?

    如果依旧使用Obj b(a)来构造,那还是会复制构造。要使用移动构造,就得使用某种方法将对象a变成右值。而函数std::move()就起到这个作用:

    std::move(var) --- 作用是类型转换:接受一个左值作为参数,返回其右值引用

    所以此时使用 Obj b(std::move(a)),就用移动构造初始化了对象b

    很多类的成员函数实际上都实现了这两种方法,比如vector的push_back():
    // std::vector方法定义void push_back(const type & value);void push_back(type && value);vector vs;string str = "hello world";vs.push_back(str);             // 此时是传入左值,push_back会深拷贝strvs.push_back(std::move(str)); // 此时传入了右值,push_back浅拷贝str作为vs中的元素                     // 同时str被置为空,不能再被使用

标签:

  • 上一篇文章: 夏日里相伴的小纠结(阿米娅酱)
  • 下一篇文章: 最后一页
  • 最新
  • C++ | 右值引用与std::move()

    右值引用-左值:可以被取地址的变量或值-右值:无法被修改,无法取地

  • 夏日里相伴的小纠结(阿米娅酱)

    —阿米娅小女儿前排提醒:严重ooc文笔极渣直面喵灾观后感(๑>؂<๑)收

  • 证券日报:适度加大A股融资融券力度

    证券日报:适度加大A股融资融券力度

  • 十大稀有的天然石头 这十种珍稀极品石头原石)

    hello大家好,我是城乡经济网小晟来为大家解答以上问题,十大稀有的天

  • 应对暑期驾考高峰!济南8月7日起实行科目一夜考机制 全市6个考点可预约

    齐鲁网·闪电新闻8月1日讯 8月1日上午,济南市公安局交通警察支队车辆

  • 骆驼股份:今年新取得18个低压锂电定点项目,预计在2025年以后实现量产供货

    骆驼股份近期在接受调研时表示,公司EFB和AGM电池、驻车空调电池、辅助

  • ​西平县权寨镇:文化合作社戏曲演出 助力乡村文化振兴_焦点快报

    为丰富广大基层群众业余文化生活,推进中华传统戏曲文化传承与发展,助

  • 天天视点!美人如画结局是什么? 美人如画的剧情介绍

    美人如画结局是什么?《美人如画》结局是徐恨毒药解除了,和江嘉沅破

  • DNF神识之种有什么用(DNF神识之种介绍)-世界微资讯

    1、详细答案:2、希洛克留下的神识种子。3、可用于在攻坚战商店中购买

  • 圣显厅三重试炼怎么过?鹿野院平藏适合什么圣遗物?-环球热文

    圣显厅三重试炼怎么过?试炼1:来到位置,往西边看,就可以看到第一

  • 泸定桥在哪里?泸定桥海拔多少米?泸定桥景区海拔多少米?

    泸定桥在哪里?泸定桥在甘孜藏族自治州。泸定桥又名大渡桥,是中国四

  • 京津冀深化体育产业协同发展 将共同推动冬奥场馆共用共享

    河北日报讯(记者赵瑞雪)为携手推进京津冀体育产业协同发展迈上新台阶

  • 全链条促进汽车消费

    汽车产业链条长,涉及生产、加工、销售等众多部门,在提振消费、拉动投

  • 环球热资讯!鸡汤怎么炖才又浓又黄?鸡汤炖出来不黄主要是什么原因呢?

    鸡汤怎么炖才又浓又黄?第1招就是把鸡放进冰箱的冷冻室里面冷冻上3~4

  • 世界报道:怪物猎人崛起霞龙中毒怎么解 (怪物猎人崛起霞龙在哪打)

    怪物猎人崛起霞龙中毒怎么解?悬崖瀑布附近有环境生物轱辘蛇,抓一只

  • 打造杭州宋韵文化新名片,大型舞台剧《苏堤春晓》启动|环球播报

    该剧由杭州市委宣传部、杭州文广集团指导,杭州演艺集团与中国国家话剧

  • 旅游
    • 期货交易时间是什么时候?期货交易的功能有哪些?

    • 天天新消息丨京商力荐 | 新媒体上线!→ 请带走这份清凉开胃美食纪录片,不谢

    • 每日速读!新都退资金总流向介绍 新都退主力控盘是什么?

    • 西班牙将接任欧盟轮值主席国-世界热点评