zoukankan      html  css  js  c++  java
  • 右值引用深入探讨

    假若X这个类型重载了拷贝构造以及移动构造。

    那么思考一下:

    void foo(X&& x)
    {
      X anotherX = x;
      // ...
    }

    哪个构造函数将会被调用?在这里x是右值引用类型,那么他是右值还是左值呢?之前对左值和右值的定义中已经表明了,如果我们可以对其进行取址操作,那么他就是左值,

    所以你可以对右值引用进行取址操作吗?

    于是,右值引用的设计者这样说:

    “右值引用变量既可以是右值也可以是左值,这取决于:如果他有名字,那么他是左值,否则,为右值”。

    所以在上面的例子中,x是有名字的,所以他是左值!所以调用的是拷贝构造函数。

    接着看下面这个例子:

    X&& goo();
    X x = goo(); // 调用 X(X&& rhs) 因为goo()的返回值没有名字。
    

    其实这样也很容易理解,当右值引用有名字的时候,这代表这个变量有可能在其他地方被引用到,那么一旦被看作是右值,那么就危险了,因为右值的意思是,这个值是无所谓的,或者说这个值里面的内容我们不关心,所以我们才会对他进行swap操作,或者其他对其有副作用的操作,因为反正右值里面的东西是“垃圾堆”,我们忘里面扔就好了,但是如果他会被其他人引用到,那么这个垃圾堆就会产生危害。而当右值引用没名字的时候,我们也无法对他进行引用,所以我们可以大胆放心的把他当作右值进行使用。

    看下面一个例子:

    Base(Base const & rhs); // non-move semantics
    Base(Base&& rhs); // move semantics

    那么他的子类Derived应该如何实现呢?

    Derived(Derived const & rhs) 
      : Base(rhs)
    {
      // Derived-specific stuff
    }

    这样写很正常,没什么问题,注意:会有一个类型转换在里面。

    那move constructor怎么写?

    Derived(Derived&& rhs) 
      : Base(rhs) // wrong: rhs is an lvalue
    {
      // Derived-specific stuff
    }

    当然,我们想调用的是Base的move构造,但是这里参数rhs是有名字的,所以我们调用错了,这里就可以使用std::move来进行转换一下。

    Derived(Derived&& rhs) 
      : Base(std::move(rhs)) // good, calls Base(Base&& rhs)
    {
      // Derived-specific stuff
    }

     接下来,看下面的代码:

    X foo()
    {
      X x;
      // perhaps do something to x
      return x;
    }

    同样,X重载了拷贝构造以及移动构造。

    这时候你的小聪明作祟,心想,这样不是拷贝了好几次嘛,于是你把代码改成这样:

    X foo()
    {
      X x;
      // perhaps do something to x
      return std::move(x); // making it worse!
    }

    不幸的是,这样反倒使得效率更低。我们都知道现代的编译器会进行一些优化,在不影响代码逻辑的前提下。

    那么我相信大家一定听说过返回值优化这个东西,所以如果你使用第一种返回方式,那么X的构造可能只有一次,而第二种小聪明的返回方式会调用默认构造+移动构造,反而效率更低。所以为了更好的使用移动语义,你需要对编译器优化进行一定的了解,否则有可能画蛇添足。

  • 相关阅读:
    HBase 高性能加入数据
    Please do not register multiple Pages in undefined.js 小程序报错的几种解决方案
    小程序跳转时传多个参数及获取
    vue项目 调用百度地图 BMap is not defined
    vue生命周期小笔记
    解决小程序背景图片在真机上不能查看的问题
    vue项目 菜单侧边栏随着右侧内容盒子的高度实时变化
    vue项目 一行js代码搞定点击图片放大缩小
    微信小程序进行地图导航使用地图功能
    小程序报错Do not have xx handler in current page的解决方法
  • 原文地址:https://www.cnblogs.com/houhoujun/p/4416128.html
Copyright © 2011-2022 走看看