forward和完美转发

        std::move(value)是独立于值的右值引用,一个右值引用参数作为函数的形参,在函数内部再转发该参数的时候已经变成了一个左值,并不是它原来的类型了。

template
void forwardValue(T& val)
{
    processValue(value);    ///右值参数会变成左值
}

template
void forwardValue(constT& val)
{
    processValue(value);    ///参数都变成常量左值引用了
}

        上面的参数都没有按照原本的类型进行转发。

        因此,我们需要一种方法能按照参数原来的类型转发到另一个函数,这种转发被称为完美转发。所谓完美转发,是指在函数模板中,完全依照模板的参数的类型(即保持参数的左值,右值特征),将参数传递给函数模板中调用的另外一个函数。C++11中提供了这样的一个函数std::forward,它是为转发而生,不管参数是T&&这种未定的引用还是明确的左值引用或者右值引用,它会按照参数本来的类型转发。

#include 
using namespace std;

void PrintT(int& t)
{
    cout << "lvalue" << endl;
}

template
void PrintT(T&& t)
{
    cout << "rvalue" << endl;
}

template
void TestForward(T&& v)
{
    PrintT(v);
    PrintT(std::forward(v));
    PrintT(std::move(v));
}

int main()
{
    TestForward(1);
    cout << endl;

    int x = 1;
    TestForward(1);
    cout << endl;

    TestForward(std::forward(x));

    return 0;
}

        测试结果如下所示:

forward和完美转发_第1张图片

        我们来分析下测试结果:

        TestForward(1):由于1是右值,所以未定的引用类型T&&v被一个右值初始化后变成了一个右值引用,但是在TestForward函数体内部,调用PrintT(v)时,v又变成了一个左值(因为在这里它已经变成了一个具名的变量,所以它是一个左值),因此,第一个PrintT被调用,打印出了"lvalue"。调用PrintT(std::forward(v))时,由于std::forward会按照参数原来的类型转发,因此,它还是一个右值(这里已经发生了类型推导,所以这里的T&&并不是一个未定的引用类型),会调用void PrintT(T&& t)函数。调用PrintT(std::move(v))是将v变成一个右值(v本身也是一个右值),因此,它将输出rvalue。

你可能感兴趣的:(深入应用C++11,c++,开发语言)