为什么 std::forward 在传输左值时返回右值? [重复]

问题描述 投票:0回答:1

据说 std::forward() 完美将左值转发到左值,将右值转发到右值。但下面的代码似乎显示出不同的结论?

当我运行下面的代码时

#include <iostream>

class A {
 public:
    int x;

    A() {x = 0;}
    explicit A(int x) : x(x) {}

    A& operator= (A&& other) {
        std::cout << " && ="  << std::endl;
        x = other.x;
    }

    A& operator= (const A& other) {
        std::cout << " & ="  << std::endl;
        x = other.x;
    }
};

int main() {
    A p1(1), p2, p3;
    p2 = p1;
    p3 = std::forward<A>(p1);
    return 0;
}

结果是:

 & =
 && =

看起来

std::forward<A>(p1)
p1
作为右值转发。

std::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);
    }

gdb 显示,当运行

p3 = std::forward<A>(p1);
时,它会进入第一个函数
forward(typename std::remove_reference<_Tp>::type& __t) noexcept
并返回类型为
A &&

的值
(gdb) p __t
$2 = (std::remove_reference<A>::type &) @0x7fffffffd1cc: {
  x = 1
}
(gdb) p static_cast<_Tp&&>(__t)
$3 = (A &&) @0x7fffffffd1cc: {
  x = 1
}

我完全困惑了。您能解释一下调用 std::forward() 时发生了什么吗?如果

std::forward<A>(p1)
p1
作为右值转发,那么 std::forward 和 std::move 有什么区别?

c++ c++11 rvalue-reference perfect-forwarding
1个回答
1
投票

如果

std::forward<A>(p1)
将 p1 作为右值转发,那么
std::forward
std::move
有什么区别?

区别在于

std::forward<A&>(p1)
返回左值,而
std::move
则不返回。

你误用了

std::forward
。传递常量模板类型参数是没有意义的。当函数具有从函数参数推导出类型的转发引用时,它们非常有用:示例:

template<class T>
void foo(T&& ref) {
    T t = std::forward<T>(ref); // copy or move

...
foo(p1); // T is deduced as A&
© www.soinside.com 2019 - 2024. All rights reserved.