move与forward实现原理

2021-04-03  本文已影响0人  devilisdevil

move与forward的作用

move

move原理

move就是把不论左值右值都强转为右值,也就是比如int&&这种类型。
move之后表示传的这个参数,你后面不要再用了,或者说表示传的这个参数后面没人会用了,你想怎么样怎么样吧(所以我们在移动构造函数或是赋值运算符中可以把参数的这个右值引用随便修改,,当然也不是随便啦,通常比如我们把指针复制过来,原来的指针赋值为nullptr)

move具体实现

  /**
   *  @brief  Convert a value to an rvalue.
   *  @param  __t  A thing of arbitrary type.
   *  @return The parameter cast to an rvalue-reference to allow moving it.
  */
  template<typename _Tp>
    constexpr typename std::remove_reference<_Tp>::type&&
    move(_Tp&& __t) noexcept
    { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }

forward

forward原理

本来当前函数在用T&&x接收完参数之后,你想要再把x传给其它函数,但是此时x是一个有名变量,也就是说不管原来传进来的是一个左值右值,现在x都是一个左值了,其它函数再接收的话只会当成左值来接收。

所以就有了forward来进行完美转发,forward<T>(x)返回T&&类型,也就是说

所以说下面这两个代码基本等价

template<typename T>
void f1(T&& t) {
  f2(static_cast<T>(t));
}
template<typename T>
void f1(T&& t) {
  f2(forward<T>(t));
}

细小区别就是,forward版本中,验证了t和T是否一致,它不允许int&&类型被转为int&类型,即下面的写法运行会报错

int x = 3;
forward<int&>(move(x));
// or
forward<int&>(3);

我们通常也不应该这么用forward。。有一个T&&t的定义,然后就用forward<T>(t)转发就好

forward具体实现

  /**
   *  @brief  Forward an lvalue.
   *  @return The parameter cast to the specified type.
   *
   *  This function is used to implement "perfect forwarding".
   */
  template<typename _Tp>
    constexpr _Tp&&
    forward(typename std::remove_reference<_Tp>::type& __t) noexcept
    { return static_cast<_Tp&&>(__t); }

  /**
   *  @brief  Forward an rvalue.
   *  @return The parameter cast to the specified type.
   *
   *  This function is used to implement "perfect forwarding".
   */
  template<typename _Tp>
    constexpr _Tp&&
    forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
    {
      static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
            " substituting _Tp is an lvalue reference type");
      return static_cast<_Tp&&>(__t);
    }

参数就是原始的类型的左值或者右值引用,这样就根据重载调用某一个具体函数,然后再强转为_Tp&&的引用类型返回

补充知识

remove_reference的作用与原理

  /// remove_reference
  template<typename _Tp>
    struct remove_reference
    { typedef _Tp   type; };

  template<typename _Tp>
    struct remove_reference<_Tp&>
    { typedef _Tp   type; };

  template<typename _Tp>
    struct remove_reference<_Tp&&>
    { typedef _Tp   type; };

很显然就是针对不同类型,T,T &,T &&,分别重载,定义出只返回不带引用符号的T

引用折叠

引用折叠是出现在模板参数是T&& t或者T& t的情况

refs

上一篇 下一篇

猜你喜欢

热点阅读