C++ 成员函数声明的参数列表后面的单个符号AND是什么意思?

C++ 成员函数声明的参数列表后面的单个符号AND是什么意思?,c++,c++11,C++,C++11,从答案来看 我知道&&意味着当对象是右值引用时将调用该成员。但是,一个“与”是什么意思呢?它与没有符号有什么不同?这意味着当对象是左值引用时,将调用该成员 [C++11:9.3.1/5]:可以使用ref限定符(8.3.5)声明非静态成员函数;见13.3.1 [C++11:13.3.1/4]:对于非静态成员函数,隐式对象参数的类型为 对于未使用ref限定符或使用和ref限定符声明的函数,“对cvX”的左值引用 对于使用和&ref限定符声明的函数,“对cvX的右值引用” 其中,X是函数为成员的类

从答案来看


我知道
&&
意味着当对象是右值引用时将调用该成员。但是,一个“与”是什么意思呢?它与没有符号有什么不同?

这意味着当对象是左值引用时,将调用该成员

[C++11:9.3.1/5]:
可以使用ref限定符(8.3.5)声明非静态成员函数;见13.3.1

[C++11:13.3.1/4]:
对于非静态成员函数,隐式对象参数的类型为

  • 对于未使用ref限定符或使用
    ref限定符声明的函数,“对cv
    X
    ”的左值引用
  • 对于使用
    和&
    ref限定符声明的函数,“对cv
    X
    的右值引用”
其中,
X
是函数为成员的类,cv是成员函数声明上的cv限定。[……]

(还有一些我找不到的规则)

如果没有ref限定符,则始终可以调用该函数,而不考虑调用该函数的表达式的值类别:

struct foo
{
    void bar() {}
    void bar1() & {}
    void bar2() && {}
};

int main()
{
    foo().bar();  // (always fine)
    foo().bar1(); // doesn't compile because bar1() requires an lvalue
    foo().bar2();
    
    foo f;
    f.bar();      // (always fine)
    f.bar1();
    f.bar2();     // doesn't compile because bar2() requires an rvalue
}
(谢谢裁判官) 但是,一个“与”是什么意思呢

该函数只能在左值上调用,不能在右值上调用

它与没有符号有什么不同

如果没有ref限定符,您可以在左值或右值上调用函数


有了ref限定符,您只能对相应的值类别调用函数。

对于右值和左值,都可以调用没有ref限定符的函数。带有
&&
ref限定符的函数只能为右值调用。带有
&
ref限定符的函数只能为左值调用

class No { void foo(); };
class L { void foo() &; };
class R { void foo() &&; };

No().foo(); // valid
No no; no.foo(); // valid
L().foo(); // invalid
L l; l.foo(); // valid
R().foo(); // valid
R r; r.foo(); // invalid
不幸的是,我只能在5.5/6中找到这个规则,它只适用于指向成员取消引用表达式的指针。我知道它在其他方面也适用

此外,您不能重载ref限定符和no ref限定符,请参阅13.1/2 bullet 3。您可以在
&
&
上过载


(由于我对标准的搜索没有结果,LRiO的答案现在也包含了所有信息。)

是的,但这不是默认的吗?我没有足够的信心发布答案,因为我没有太多地使用ref限定符,但我认为不使用它允许在右值或左值上调用成员函数,添加时,它会限制对相应值类别的调用@clin18不能用没有ref限定符的函数重载带有ref限定符的函数。你要么两个都有,要么一个都没有。@LightnessRacesinOrbit你可以引用13.1/2,第三颗子弹。该死,错过了一些机会!我很高兴看到您在示例中修改了我的无意义注释:)我也放弃了为它找到一个合适的引号><+1[over.match.funcs]p4确定隐式obejct参数,它会影响哪些(如果有)重载是可行的,通过p4,既不
&
也不匹配任何限定符rvalue。p5然后包含一个特殊的异常,任何限定符都不能绑定到右值。
class No { void foo(); };
class L { void foo() &; };
class R { void foo() &&; };

No().foo(); // valid
No no; no.foo(); // valid
L().foo(); // invalid
L l; l.foo(); // valid
R().foo(); // valid
R r; r.foo(); // invalid