为什么rvalue引用参数更喜欢对左值引用参数的const左值引用?

时间:2017-01-04 07:11:58

标签: c++ c++11 move rvalue-reference

以下是VS2015中的一些代码:

class Elem 
{
public:
    Elem(int i) : a(i) {}
    Elem(Elem && other) = default;
    Elem(const Elem & other) = default;
private:
    int a;
};

int main()
{
    std::vector<Elem> vv;

    // case 0
    vv.push_back(Elem{ 0 }); // call push_back(Elem &&);

    // case 1
    Elem e1{ 1 };
    vv.push_back(e1); // call push_back(const Elem &);

    // case 2
    Elem e2{ 2 };
    auto & lref = e2;
    vv.push_back(lref); // call push_back(const Elem &);

    // case 3
    Elem e3{ 3 };
    auto && rref = std::move(e3);
    vv.push_back(rref); // call push_back(const Elem &);

    // case 4
    Elem e4{ 4 };
    vv.push_back(std::move(e4)); // call push_back(Elem &&);

    return 0;
}

在案例3中,rref的类型是右值引用,其值类别为lvalue,并调用push_back(const Elem &)

在案例4中,根据Effective Modern C ++ Item 23,std::move的实现类似于

// C++ 14    
template<typename T>
decltype(auto) move(T&& param)
{
    using ReturnType = remove_reference_t<T>&&;
    return static_cast<ReturnType>(param);
}

std::move(e4)的类型为Elem &&,其值类别为prvalue,调用push_back(Elem &&)

lvalue T&&匹配const T &prvalue T&&匹配T&&,类型和值类别是什么表达式实际上是在Tconst T &T &&之间的重叠解析期间做的?

很抱歉没有清楚地描述我的问题。正如许多链接所说,如果参数的值类别为prvalue,则会调用T&&的函数;值类别为lvalue,将调用const T &的函数。

我可以简单地说参数的类型用于重载解析,而当参数的类型是参考时,会检查值类别的参考绑定吗?

2 个答案:

答案 0 :(得分:1)

rref是左值,因为它有一个名称,因此调用push_back(const Elem &)move到命名变量是没用的,但是如果你坚持它,你可以将你的代码更改为:

// case 3
Elem e3{ 3 };
auto && rref = std::move(e3);
vv.push_back(std::forward<decltype(e3)>(rref));

然后调用push_back(Elem &&)。或者只是做你在案例4中所做的事情。

答案 1 :(得分:0)

当您指定变量名称(在本例中为“e3”)并使用此变量传递函数时,它变为左值。这就是为什么它调用函数“push_back”的左值版本。但是当你在案例4中作为“std :: move(e4)”传递时,它将作为rvalue传递,这就是为什么它调用rvalue引用版本的“push_back”函数。

刚刚通过网络我发现这个链接以几乎相似的术语解释了右值参考。你可以查看这个链接。

http://simpletechtalks.com/rvalue-references/