const lvalue reference和rvalue reference之间的重载分辨率

时间:2016-11-12 15:57:53

标签: c++ c++14 rvalue-reference overload-resolution

#include <iostream>
#include <string>

void fnc (const std::string&)
{
    std::cout<<1;
}

void fnc (std::string&&)
{
    std::cout<<2;
}

int main()
{
    fnc ("abc");
}

所有编译器都选择std::string&&fnc,这是合乎逻辑的,因为临时std::string是为参考绑定创建的,但我无法找到,其中它是在C ++ 14 Standard中描述的。 我在那里找到了一个段落(3.2):

  

- 标准转换序列S1是比转换序列更好的转换序列   标准转换序列S2,如果

     

[...]

     

- S1和S2是参考绑定(8.5.3),两者都不是指   声明的非静态成员函数的隐式对象参数   没有ref-qualifier,S1将右值引用绑定到 rvalue   和S2绑定一个左值参考

但事实并非如此,因为S1将右值引用绑定到左值(&#34; abc&#34;,const char [4]的左值)。 我在哪里可以找到描述,通过该描述选择第二个过载?

P.S。我指的是C ++ 14 Standard而不是C ++ 11,因为我知道,C ++ 11中存在一些与rvalue引用绑定相关联的缺陷报告。

3 个答案:

答案 0 :(得分:7)

首先,编译器为"abc"执行隐式数组到指针转换,因此"abc"的类型变为const char*。第二个(你可能错过了),const char*通过std::string non-explicit constructor of std::string(链接中的#5)转换为右值 const char* 。构造的std::string rvalue是第二次重载的完美匹配,因此选择了第二次重载。

答案 1 :(得分:2)

  

但事实并非如此,因为S1将左值引用绑定到左值(&#34; abc&#34;,const char [4]的左值)。

请注意,"abc"const char[4],而不是std::string。但是fnc()都将std::string作为参数,并且引用不能直接绑定到不同类型的对象。因此,首先"abc"需要隐式转换为std::string,这是一个临时的,即一个右值。然后正如标准所说,将选择右值参考过载。

答案 2 :(得分:1)

res = [(x,y) for x,y in a if (str(x) != 'nan' and str(y) != 'nan' and str(y) != 'FREE_FROM')] 无法直接传递到"abc"的任何重载中。对于它们两者,必须将其转换为(rvalue)fnc()。但是,标准中引用的规则明确选择std::string而不是fnc(std::string&&)