我有以下代码直接来自: http ://www.justsoftwaresolutions.co.uk/cplusplus/rvalue_references_and_perfect_forwarding.html
在 g++ 4.8.1 编译为: g++ -std=c++11 testforward.cpp -o testforward.exe
#include <cstdlib>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
class X
{
std::vector<double> data;
public:
X():
data(100000) // lots of data
{}
X(X const& other): // copy constructor
data(other.data) // duplicate all that data
{}
X(X&& other): // move constructor
data(std::move(other.data)) // move the data: no copies
{}
X& operator=(X const& other) // copy-assignment
{
data=other.data; // copy all the data
return *this;
}
X& operator=(X && other) // move-assignment
{
data=std::move(other.data); // move the data: no copies
return *this;
}
};
void g(X&& t)
{
std::cout << "t in g is rvalue" << std::endl ;
}
void g(X& t)
{
std::cout << "t in g is lvalue" << std::endl ;
}
template<typename T>
void f(T&&t)
{
g(std::forward<T>(t)) ;
}
void h(X &&t)
{
g(t) ;
}
int main()
{
X x;
f(x); // 1
f(X()); // 2
//h(x); //compile error
h(X()); // 3
}
据作者描述如下:
当你将右值引用与函数模板结合起来时,你会得到一个有趣的交互:如果函数参数的类型是对模板类型参数的右值引用,那么如果传递了左值,则类型参数被推断为左值引用,而普通的否则键入...
该测试的结果输出是:
t in g is lvalue
t in g is rvalue
t in g is lvalue
f(x) get "t in g is lvalue" 和预期的一样!!
f(X()) 得到 "t in g is rvalue" ,是的,这就是 std::forward 的用途
h(X()) get "t in g is lvalue",这是我的问题,你可以看到函数 h 不是模板函数,正如作者所描述的“当你将右值引用与函数模板结合起来时,你会得到一个有趣的交互”不是这种情况,这个函数仍然输出“t in g is lvalue”,这意味着这个有趣的交互不仅发生在模板函数中,也发生在正常函数中!!
如果我将代码更改为:
void h(X &&t)
{
g(std::forward<X>(t)) ;
}
我会得到“t in g is rvalue”!!!
根据测试,我可以说作者描述“当你将右值引用与函数模板结合起来时,你会得到一个有趣的交互”实际上不仅适用于模板函数,它也适用于普通函数,或者我的英语不好,所以我可以没听懂这个描述吧?!
编辑 :
void h(X &&t)
{
g(t) ;
}
void h(X &t)
{
g(t) ;
}
h(x); //get "t in g is lvalue"
h(X()); //get "t in g is lvalue"
=====================================================
void h(X &&t)
{
g(std::forward<X>(t)) ;
}
void h(X &t)
{
g(std::forward<X>(t)) ;
}
h(x); //get "t in g is rvalue"
h(X()); //get "t in g is rvalue"
看起来只有在模板函数中,我会得到 std::forward 的 cprrect 用法!!!