我正在尝试新增的右值参考(在vs2012 express中).
我不明白.给出下面的代码(大部分来自c标准,其中解释了std :: forward).
struct A { A(int& i,const float& j): m_i(i),m_j(j){} int& m_i; const float& m_j; }; template<class T,class A1,class A2> T* factory(A1&& a1,A2&& a2) { return new T(a1,a2); } void test() { A* a1 = factory<A>(1,1.2f); //How does this work ? a1->m_i = 2; }
我不明白m_i绑定到哪里.
我将基本上有一个左值引用到右值引用(&&&&),ref refpsing规则变成(&)一个简单的左值引用.但是参考什么?
解决方法
I don’t understand where is m_i binded to.
m_i绑定到A的构造函数的参数. A的构造函数在这里的论点是什么?
在这种情况下,由于工厂不将其参数转发给A(即它不使用std :: forward<>()),那么传递给A的是左值.这是因为命名了a1,命名对象是左值.
a1的类型与确定a1是左值还是右值无关.因此,即使a1具有类型rvalue-reference to int(int&&),就像程序中的情况一样,参数a1本身也是一个命名对象,因此它是一个左值.
这意味着,由于m_i具有对int的类型lvalue-reference,因此m_i可以绑定(并且实际上是绑定)到factory(lvalue)参数a1,该参数将在factory()返回时被销毁.换句话说,你留下了一个悬垂的参考.
试图取消引用它(正如你在程序中稍后所做的那样)会召唤未定义的行为.
但是,如果您的factory()函数已将其参数转发给A的构造函数:
template<class T,A2&& a2) { return new T(std::forward<A1>(a1),std::forward<A2>(a2)); }
这会导致编译器错误,因为std :: forward<>()的机制会确保左值保持左值,并且rvalues保持rvalues.尝试将左值引用绑定到右值是非法的,因此对A的构造函数的调用将失败.