涉及按值传递、引用和常量引用的 C++ 函数重载解析

C++ function overloading resolution involving pass-by-value, reference and constant reference

假设我用 C++ 中的以下 3 个签名定义了一些函数 f

void f(int x) {}
void f(int& x) {}
void f(const int& x) {}

这些函数可以共存,因为它们的参数类型不同。

现在我运行下面的代码:

int main {
   int i = 3;
   const int ci = 4;

   f(3);
   f(i);
   f(ci);
}

C++ 如何知道在这种特定情况下要调用哪个重载函数?在 C++ 中编写重载函数以避免歧义的一般规则是什么(最佳实践?)。当前的 C++14 标准是否指定了任何特定规则?

你不能超载:

void f(int x) {}
void f(const int& x) {}

鉴于这些,编译器将无法消除以下调用的歧义:

f(10);

你不能超载:

void f(int x) {}
void f(int& x) {}

鉴于这些,编译器将无法消除以下调用的歧义:

int i = 0;
f(i);

您可以重载:

void f(int& x) {}
void f(int const& x) {}

鉴于这些,您可以使用:

int i = 0;
f(i);    // Resolves to f(int&)
f(10);   // Resolves to f(int const&)

void f(int x) {} 该函数将有一个对象的副本,它是临时的,所以如果您想修改值或传递大量数据,请不要使用它。

void f(int& x) {} 相同但通过引用传递,因此它是来自 c 的指针,但您可以像普通对象一样使用它。您将能够修改它,并且最好传递大量数据,因为编译器不会复制它。

void f(const int& x) {} 参数前的const表示对象不可修改。顺便说一句,您不必在 main 中将其声明为 const。

我不确定函数调用案例部分,所以我不会回答 ;)

这三个调用都是不明确的,所以程序无法编译。

f(3);

这可以使用第一个或第三个重载。都一样好,所以叫法含糊。

f(i);

这可以使用第一个、第二个或第三个重载。第二个比第三个好;在可能的情况下,绑定到 int& 优于绑定到 const int&。所以以这种方式在 cv-qualification 上超载是可以的。但是第一次和第二次重载之间存在歧义。

f(ci);

这可以使用第一个或第三个重载。同样,它们同样出色,因此调用不明确。


标准明确规定了重载决议的规则。它们非常复杂,所以以一种让 reader 很难判断将调用哪个重载的方式重载函数是个坏主意。你可以找到规则 here.