C++ 将右值引用传递给采用左值引用的函数

Dre*_*mer 6 function rvalue-reference c++11

当我阅读Scott Meyer 撰写的《Effective Modern C++》,了解 std::forward 函数如何工作时,我遇到了一个我不太明白的问题。假设我们有一个foo如下函数:

template<typename T>
void foo(T&& fooParam)
{
    ...
    someFunc(std::forward<T>(fooParam));
}
Run Code Online (Sandbox Code Playgroud)

在书中,斯科特解释说std::forward<T>可以通过以下方式实现:

template<typename T>
T&& forward(typename remove_reference<T>::type& param)
{
    return static_cast<T&&>(param);
}
Run Code Online (Sandbox Code Playgroud)

假设传递给的参数foo是类型的右值Widget。然后std::forward函数模板将像这样初始化:

Widget&& forward(Widget& param)
{ return static_cast<Widget&&>(param); }
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,当fooParam(类型为Widget &&)传递给 时,采用matchstd::forward类型参数的函数如何?我知道它本身是一个左值。但它的类型仍然是右值引用 ( ) 对吗?他们怎么可能相配呢?Widget& paramfooParamfooParamWidget &&

如果一个采用左值引用类型参数的函数可以通过右值引用传递,那么这个函数可以做任何它想做的事情,甚至修改传入的右值(就像一个临时对象)。这对我来说没有意义...

小智 7

#include <iostream>
using std::cout;
using std::endl;

template<class T>
void my_print(T&& arg)
{
    my_print_impl(std::forward<T>(arg));
}
template<class T>
void my_print_impl(T& arg)
{
    cout << "lvalue reference" << endl;
}

template<class T>
void my_print_impl(T&& arg)
{
    cout << "rvalue reference" << endl;
}

int main()
{
    int i = 1;
    int & l_ref = i;
    int && r_ref = 1;
    my_print(l_ref);            //print lvalue reference
    my_print(r_ref);            //print lvalue reference
    my_print(std::move(l_ref)); //print rvalue reference
    my_print(1);                //print rvalue reference, 1 is a true rvalue
    system("pause");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

正如您所说, r_ref 是左值引用,您不应该将其作为右值引用进行匹配。如果您想将参数作为右值引用传递,请使用std::move()或仅将右值传递给您的函数。