<分区>
我正试图在 C++ 中解决完美转发问题,因此我编写了以下快速而肮脏的代码来测试它。
class CValue
{
public:
CValue(int i) :
m_i(i)
{
printf("Default constructor called!\r\n");
}
CValue(const CValue& src) :
m_i(src.m_i)
{
printf("Copy constructor called!\r\n");
}
CValue(CValue&& src) :
m_i(src.m_i)
{
printf("Move constructor called!\r\n");
}
CValue& operator=(const CValue& src)
{
m_i = src.m_i;
printf("Copy assignment called!\r\n");
return *this;
}
CValue& operator=(CValue&& src)
{
m_i = src.m_i;
printf("Move assignment called!\r\n");
return *this;
}
int m_i;
};
template <typename T>
void PerfectForwarding(T&& tValue)
{
T tValue1 = tValue;
tValue1.m_i = 10;
}
int _tmain(int argc, _TCHAR* argv[])
{
CValue v(0);
PerfectForwarding(v);
printf("%d\r\n", v.m_i);
return 0;
}
当我构建并运行此代码作为控制台应用程序时,我得到了答案 10,而我期望的是 0。
这行好像是:
T tValue1 = tValue;
在 PerfectForwarding 函数中被解析为:
CValue& tValue1 = tValue;
代替:
CValue tValue1 = tValue;
所以编译器将 T 解析为 CValue&,这是我没想到的。
我尝试通过显式声明模板参数类型从 _tmain 调用函数,即
PerfectForwarding<CValue>(v);
但是编译失败并出现以下错误:
error C2664: 'void PerfectForwarding<CValue>(T &&)' : cannot convert
argument 1 from 'CValue' to 'CValue &&'
with
[
T=CValue
]
You cannot bind an lvalue to an rvalue reference
我可以通过将 PerfectForwarding 函数中的行更改为以下内容来强制执行所需的行为:
typename std::remove_reference<T>::type tValue1 = tValue;
但我认为这不是必要的。根据引用折叠规则,参数类型 (T&&) 应该变成 CValue&(如 T&& & -> T&),但是 T 本身应该只是 CValue,对吧?这是 VC12 编译器处理右值引用的错误,还是我误解了右值引用和模板?
我在调试中使用 Visual Studio 2013(VC12 编译器)并关闭所有优化。