使用其他相同签名重载函数以接受引用和const引用

Zho*_* Ma 1 c++ overloading const reference

代码如下:

struct A {};   

void f (A& a) {std::cout << "No const" << std::endl;} 

void f (const A& a) {std::cout << "const" << std::endl;} 

int main(){
   f(A()); // indicated as line A, output will be "const".
}
Run Code Online (Sandbox Code Playgroud)

问题1):

为什么line A的输出是"const",即使它A()是一个非const对象?

我认为编译器产生的代码相当于:

const A tempA;
f(tempA); 
Run Code Online (Sandbox Code Playgroud)

是对的吗 ?

问题2),如果修改了两个f函数,则更改对值类型的引用

void f (A a) {std::cout << "No const" << std::endl;} 

void f (const A a) {std::cout << "const" << std::endl;}  
Run Code Online (Sandbox Code Playgroud)

以上代码无法编译.编译器给出"函数f的重新定义"错误.我可以理解为什么错误是由编译器发出的,因为它可以转换const AA反之亦然.因此,无法在编译时决定.是对的吗 ?

我仍然很好奇,它在c ++规范中定义得很好吗?

Pio*_*cki 5

为什么A行的输出是"const",即使A()是没有const的对象?

A()表达式创建一个不能被非const左值引用绑定的prvalue临时值,因此void f (const A& a)是唯一可行的重载.

我仍然很好奇,它在c ++规范中定义得很好吗?

§13.1[over.load]/p3:

- 参数声明仅在存在或不存在const和/或volatile等效时有所不同.也就是说,在确定声明,定义或调用哪个函数时,将忽略每个参数类型的constvolatile类型说明符.[ 例如:

typedef const int cInt;
int f (int);
int f (const int);           // redeclaration of f(int)
int f (int) { /* ... */ }    // definition of f(int)
int f (cInt) { /* ... */ }   // error: redefinition of f(int)
Run Code Online (Sandbox Code Playgroud)

- 结束例子 ]

仅以这种方式忽略参数类型规范最外层的constvolatile类型说明符; constvolatile掩埋的参数类型规范内型说明符显著,并且可以用来区分重载函数声明.特别是,对于任何类型T,"指向T","指向const T"和"指向"的指针volatile T被认为是不同的参数类型,如"对T的引用const T","引用"和"引用volatile T".

对于类型的参数Aconst A相同的转换序列适用于由任何可转换为的参数初始化时A,编译器将永远无法在两者之间进行选择.

对于类型的参数A&,并const A&可以有不同的表现形式,使编译器可以选择更好的转换序列,或从一组候选排除任何候选人.