我正在试验新添加的右值引用(在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折叠规则,它只是一个普通的左值引用。但是指的是什么?
发布于 2013-04-12 18:23:21
我不明白m_i绑定到哪里了。
m_i绑定了A的构造函数的参数。这里A的构造函数的参数是什么?
在这种情况下,由于factory不将其参数转发给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, class A1, class A2>
T* factory(A1&& a1, A2&& a2)
{
return new T(std::forward<A1>(a1), std::forward<A2>(a2));
}这将导致编译器错误,因为std::forward<>()的机制将确保左值保持左值,而右值保持右值。试图将左值引用绑定到右值是非法的,因此调用A的构造函数将失败。
发布于 2013-04-12 18:22:37
但是引用了什么?
这是一种未定义的行为。正如您所猜测的那样,它是对一个在函数factory的堆栈中被析构的临时函数的引用。要在编译时捕获此类问题,需要使用std::forward
template<class T, class A1, class A2>
T* factory(A1&& a1, A2&& a2)
{
return new T(std::forward<A1>(a1), std::forward<A2>(a2));
}https://stackoverflow.com/questions/15968752
复制相似问题