首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >错误转发右值引用

错误转发右值引用
EN

Stack Overflow用户
提问于 2013-04-12 18:16:22
回答 2查看 193关注 0票数 6

我正在试验新添加的右值引用(在vs2012 express中)。

我还是不明白一些事情。给出了下面的代码(其中大部分摘自c++标准,其中解释了std::forward )。

代码语言:javascript
复制
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折叠规则,它只是一个普通的左值引用。但是指的是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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的构造函数:

代码语言:javascript
复制
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的构造函数将失败。

票数 10
EN

Stack Overflow用户

发布于 2013-04-12 18:22:37

但是引用了什么?

这是一种未定义的行为。正如您所猜测的那样,它是对一个在函数factory的堆栈中被析构的临时函数的引用。要在编译时捕获此类问题,需要使用std::forward

代码语言:javascript
复制
template<class T, class A1, class A2>
T* factory(A1&& a1, A2&& a2)
{
    return new T(std::forward<A1>(a1), std::forward<A2>(a2));
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15968752

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档