C++;-编译器如何在以引用类型作为参数的重载函数之间做出决定? 在学习C++的时候,我遇到了复杂的转换序列,我遇到了一个我自己无法解决的问题。p> void g(const double) { std::cout << "void g(const double)" << std::endl; } void g(const double&&) { std::cout << "void g(const double&&)" << std::endl; } int main(int argc, char **argv) { g(3.14); return (0); } void g(常数双精度) { std::cout

C++;-编译器如何在以引用类型作为参数的重载函数之间做出决定? 在学习C++的时候,我遇到了复杂的转换序列,我遇到了一个我自己无法解决的问题。p> void g(const double) { std::cout << "void g(const double)" << std::endl; } void g(const double&&) { std::cout << "void g(const double&&)" << std::endl; } int main(int argc, char **argv) { g(3.14); return (0); } void g(常数双精度) { std::cout,c++,c++11,implicit-conversion,overloading,C++,C++11,Implicit Conversion,Overloading,在重载解析中,直接引用绑定是一种身份转换(即使添加了限定符);对于double来说,匹配double的参数或对-double的引用并没有好坏之分 在您的示例中,const有点像是在转移注意力。对于非引用类型,f(const double),顶级const不是函数签名的一部分;在f(const double&)中,它仍然是直接绑定,因此仍然是身份转换 所以,前两种情况都是身份转换,没有理由选择其中一种 在案例3中,规则C++14[over.ics.rank]/3.1.3适用: 标准转换序列S1是比

在重载解析中,直接引用绑定是一种身份转换(即使添加了限定符);对于
double
来说,匹配
double
的参数或对-
double
的引用并没有好坏之分

在您的示例中,
const
有点像是在转移注意力。对于非引用类型,
f(const double)
,顶级
const
不是函数签名的一部分;在
f(const double&)
中,它仍然是直接绑定,因此仍然是身份转换

所以,前两种情况都是身份转换,没有理由选择其中一种

在案例3中,规则C++14[over.ics.rank]/3.1.3适用:

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

  • [……]
  • S1和S2是引用绑定(8.5.3),都没有引用 声明的非静态成员函数没有ref限定符,S1将右值引用绑定到右值,S2绑定左值引用
此规则允许为同一类型的右值和左值重载函数。

重载解析表 此表总结了谁可以去哪里:

    ---------------------------------------------------------------------------------
               Caller    |   lvalue     | const lvalue |   rvalue     | const rvalue 
         Function        |              |              |              |  
    ---------------------------------------------------------------------------------
    [a]  f(X& x)         |    V (1)     |              |              |
    ---------------------------------------------------------------------------------
    [b]  f(const X& x)   |    V (2)     |      V       |    V (3)     |    V (2)
    ---------------------------------------------------------------------------------
    [c]  f(X&& x)        |              |              |    V (1)     |
    ---------------------------------------------------------------------------------
    [d]  f(const X&& x)  |              |              |    V (2)     |    V (1)
    ---------------------------------------------------------------------------------
  • 以上所有签名可以共存
  • V符号标记可能的有效分辨率
  • 当同一呼叫者有多个有效的解析时,它们被编号,(1)比(2)更匹配,以此类推
  • 使用上述任何一种重载byval版本都没有意义,除非有额外的区别,比如方法上的const等。 添加byvalue版本:f(X X)不能很好地与上述任何组合一起工作-在大多数情况下,它会导致任何调用的歧义,在某些情况下,它只会更喜欢byval版本(如果它仅与[a]共存-除左值外的任何调用都会更喜欢byvalue版本,而左值调用会导致歧义)
  • 签名[d]很少使用,请参见:

您是否意识到
void g(const double)
void g(double)
在重载解决方面是相同的?我不完全确定,但我认为
void g(const double&)
void g(double&)是相同的
too\。类似3.14的文字。在重载上下文中,将右值作为右值引用传递比将右值作为常量引用传递更可取。将右值作为常量引用传递被认为是“更糟糕的”而不是作为右值引用、值引用或常量引用进行传递。但是,按值传递、作为右值引用或常量引用在首选项方面被认为是“相等”的,因此具有歧义性。这是简短的胶囊摘要版本。@RSahu后两者不相同(其中只有一个可以接受类型为
constdouble
)的xvalue@M.M,感谢您的澄清。原则上,一旦您有一个函数按值接收一个对象,请说
void f(T)
,并且您决定重载
f
,以便能够通过引用获取该对象,请说
void f(T&)
-您将为重载解析过程中出现的歧义创建空间。您通常希望避免此类API。您通常希望基于右值和(常量)左值引用重载,或者只传递值,但不能同时传递两者。
void g(const double&&)
{
    std::cout << "void g(const double&&)" << std::endl;
}

void g(const double&)
{
    std::cout << "void g(const double&)" << std::endl;
}

int main(int argc, char **argv)
{
    g(3.14);    
    return (0);
}
    ---------------------------------------------------------------------------------
               Caller    |   lvalue     | const lvalue |   rvalue     | const rvalue 
         Function        |              |              |              |  
    ---------------------------------------------------------------------------------
    [a]  f(X& x)         |    V (1)     |              |              |
    ---------------------------------------------------------------------------------
    [b]  f(const X& x)   |    V (2)     |      V       |    V (3)     |    V (2)
    ---------------------------------------------------------------------------------
    [c]  f(X&& x)        |              |              |    V (1)     |
    ---------------------------------------------------------------------------------
    [d]  f(const X&& x)  |              |              |    V (2)     |    V (1)
    ---------------------------------------------------------------------------------