zoukankan      html  css  js  c++  java
  • 右值引用和强制移动语义

    假设X是一个类型,那么X&&称作X的右值引用类型,于是为了区分,我们称X&为X的左值引用类型。

    右值引用和左值引用很相似,当然也有一些细微的不同点:当我们重载函数解析的时候,参考下面的例子:

    void foo(X& x); 
    void foo(X&& x); 
    
    X x;
    X foobar();
    
    foo(x); // 参数是左值,所以调用foo(X&)
    foo(foobar()); // 参数是右值,所以调用foo(X&&)

    //这些都是在编译时刻确定的。

    在任何时候,你都可以去实现这两种引用类型的重载,但是在大多数情况下,我会建议你在拷贝和赋值构造的时候使用这种重载比较好。

    X& X::operator=(X const & rhs); 
    X& X::operator=(X&& rhs)
    {
      // 移动语义:交换this和rhs
    return *this; }

    拷贝构造同理。

    警告:在上面的实现中,交换this和rhs是不够好的,我们会在之后讨论这点。

    注意:

    如果你实现了

    void foo(X&);
    

    但是没实现

    void foo(X&&);
    

    那么很明显foo将会调用参数为左值的表达式,参数为右值的情况将不会通过编译。

    如果你实现了

    void foo(X const &);
    

    但是没有实现

    void foo(X&&);
    

    那么无论作用在左值或者右值上,foo都会成功。但是他不会区分左值和右值。

    但是如果你实现了

    void foo(X&&);

    但是没有实现其他两个重载,对于右值来说当然是ok的,但是对左值是行不通的。

    之前我们说到的move语义,是对右值进行操作的,但是很可怕的是,你同样可以对左值进行move操作。

    最明显的例子就是std中的swap操作。

    template<class T>
    void swap(T& a, T& b) 
    { 
      T tmp(a);
      a = b; 
      b = tmp; 
    } 
    
    X a, b;
    swap(a, b);

    上面操作的表达式均不是右值表达式,而且也没有利用move constructor,但是我们很明确的知道使用移动语义的好处,所以我们当然希望在这里也使用到移动语义。

    于是有人来拯救我们了,c++11中有一个函数叫std::move,他的作用就是把他的参数转成右值然后返回。

    所以在c++11中的swap是这样子的:

    template<class T> 
    void swap(T& a, T& b) 
    { 
      T tmp(std::move(a));
      a = std::move(b); 
      b = std::move(tmp);
    } 

    如果T没有实现相应的构造函数(右值引用),那么swap操作将会像之前的行为一样(调用拷贝构造)。

    使用move有很多好处:

    1.对于那些实现了move语义的操作,你会得到一些性能上的提升。

    2.STL容器通常要求元素支持拷贝操作,当然如果我们支持move操作,这也会满足这些容器的要求。

     但是:

    我们看下面这个操作

    a=std::move(b);

    如果move的内部实现是一个swap操作,那么a和b的值最终会交换。

    所 以这个操作完成后,a所携带的资源并不会被释放,其实a的资源会不会被释放的关键取决于b的生存周期,或者说b所占的资源此时代表了当初那个应该被释放的 资源,然而这个资源什么时候最终会被释放呢,我们无法确定。当然如果说这个释放的时间是没有副作用的,那就皆大欢喜了,但是如果,万一这个资源必须在拷贝 的时候被释放掉,那我们非做不可,而不是做一下简单的swap。

    X& X::operator=(X&& rhs)
    {
    
      // 提前释放那些有可能产生副作用的资源
      // 确保对象目前的状态是可析构的和可拷贝的 
    // swap操作
      
      return *this;
    }
  • 相关阅读:
    HTB-靶机-Charon
    第一篇Active Directory疑难解答概述(1)
    Outlook Web App 客户端超时设置
    【Troubleshooting Case】Exchange Server 组件状态应用排错?
    【Troubleshooting Case】Unable to delete Exchange database?
    Exchange Server 2007的即将生命周期,您的计划是?
    "the hypervisor is not running" 故障
    Exchange 2016 体系结构
    USB PE
    10 months then free? 10个月,然后自由
  • 原文地址:https://www.cnblogs.com/houhoujun/p/4405010.html
Copyright © 2011-2022 走看看