涉及按值传递、引用和常量引用的 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.
假设我用 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.