为什么在成员函数上为*this指定左值引用不同于不指定任何内容?

pep*_*ppe 19 c++ c++11

考虑以下代码:

#include <iostream>
using namespace std;

struct A {
    void f() { cout << "A::f" << endl; }
    void f() const { cout << "A::f const" << endl; }
};

struct B {
    void f() & { cout << "B::f &" << endl; }
    void f() const & { cout << "B::f const &" << endl; }
};

A getA() { return A{}; }
B getB() { return B{}; }

int main() {
    getA().f();
    getB().f();
}
Run Code Online (Sandbox Code Playgroud)

打印

A::f
B::f const &
Run Code Online (Sandbox Code Playgroud)

因为B,选择了const重载,而不是非常量重载.我想这意味着为*this指定左值ref限定符与不指定任何内容有所不同.这是为什么?"隐含此参数"是否会改变类型,而const重载现在成为重载解析的更好选择?

use*_*016 19

在这种情况下:

struct A {
    void f() { cout << "A::f" << endl; }
    void f() const { cout << "A::f const" << endl; }
};

getA().f();
Run Code Online (Sandbox Code Playgroud)

两种重载都是可行的f,但非常量的重载是优选的,因为它不需要转换.

但在这种情况下:

struct B {
    void f() & { cout << "B::f &" << endl; }
    void f() const & { cout << "B::f const &" << endl; }
};

getB().f();
Run Code Online (Sandbox Code Playgroud)

第一个重载需要this是左值.但是getB().f(),结果getB()是一个prvalue,它不能绑定到非const的左值.所以这种过载是不可行的,也没有选择.

然而,第二个重载需要this是一个const值,prvalue可以绑定到:这个重载是可行的并由编译器选择.

  • @peppe,是的,但是`&`限定符限制了左值,而没有限定符根本没有限制.有一些限制显然不是没有限制! (5认同)
  • 当然,添加ref-qualifier与根本没有ref-qualifier不同,否则该功能的重点是什么?!是什么让你觉得"`&`相当于没有ref限定符"可能首先是真的? (4认同)

pep*_*ppe 6

作为参考,完全误导我的句子是[over.match.funcs]N3337的§13.3.1/ 4:

  1. 对于非静态成员函数,隐式对象参数的类型是

- 对于没有引用限定符或使用&ref-qualifier声明的函数的"对cv X的左值引用"

- 对于用&& ref-qualifier声明的函数的"对cv X的rvalue引用"

(强调我的).

所以我对为什么输出有所不同感到有点疯狂.没有或有一个&ref限定符应该根据这里相同,对吧?

那么,原因是之后在§13.3.1/ 5中潜入了一条额外的规则

对于未使用ref-qualifier声明的非静态成员函数,应用其他规则:

- 即使隐式对象参数不是const限定的,只要在所有其他方面都可以将参数转换为隐式对象参数的类型,就可以将rvalue绑定到参数.

这基本上触发了非const rvalue到非const lvalue转换,并在上面的例子中产生了所有不同.D'呃.