成员函数签名末尾的&(&符号)是什么意思?

Mar*_* B. 7 c++ c++11

我不记得是哪一次谈话,但最近我看了一些来自CppCon 2017的演讲,并且有人提到了某种旁注,唯一真正的重载方式是以operator=下列方式:

class test {
public:
    test& operator=(const test&) &;
};
Run Code Online (Sandbox Code Playgroud)

他明确强调了尾随&但没有说明它做了什么.

那它是做什么的?

dfr*_*fri 10

Ref-qualifiers不是C++ 17的特性(查看问题的标签),但是是C++ 11中引入的一个特性.

struct Foo
{
  void bar() const &  { std::cout << "const lvalue Foo\n"; }
  void bar()       &  { std::cout << "lvalue Foo\n"; }
  void bar() const && { std::cout << "const rvalue Foo\n"; }
  void bar()       && { std::cout << "rvalue Foo\n"; }
};

const Foo&& getFoo() { return std::move(Foo()); }

int main()
{
  const Foo c_foo;
  Foo foo;

  c_foo.bar();    // const lvalue Foo
  foo.bar();      // lvalue Foo
  getFoo().bar(); // const rvalue Foo
  Foo().bar();    // rvalue Foo
}
Run Code Online (Sandbox Code Playgroud)

有关简要介绍,请参阅以下博客文章:


为了解释你从CppCon谈话中重新引用的引用的意图,

"......唯一真正的超载方式operator=......"

我们访问[over.match.funcs]/1,/ 4&/ 5 [强调我的]:

/ 1 [over.match.funcs]的子条款描述了在使用重载决策的每个上下文中提交给重载决策的候选函数集和参数列表....

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

  • (4.1) - "左值参考CV X"为声明的函数不具有REF-限定符或与所述&REF-限定符

  • (4.2) - X使用&&ref-qualifier 声明的函数的"rvalue reference to cv "

where X是函数所属的类,cv是成员函数声明的cv-qualification....

/ 5 ...对于在没有ref-qualifier的情况下声明的非静态成员函数,还应用一个附加规则:

  • (5.1) - 即使隐式对象参数不是const限定的,只要在所有其他方面可以将参数转换为隐式对象参数的类型,就可以将rvalue绑定到参数.[注意:这样的参数是rvalue的事实不会影响隐式转换序列的排名. - 结束说明]

从上面的/ 5开始,出现以下重载(&省略了显式引用限定符)

struct test
{
    test& operator=(const test&) { return *this }
}
Run Code Online (Sandbox Code Playgroud)

允许将值分配给r值,例如

int main()
{
    test t1;
    t1 = test(); // assign to l-value
    test() = t1; // assign to r-value
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我们使用&ref-qualifier 显式声明重载,[over.match.funcs] /5.1不适用,并且只要我们不提供使用&&ref-qualifier 声明的重载,r值赋值将不会允许.

struct test
{
    test& operator=(const test&) & { return *this; }
};

int main()
{
    test t1;
    t1 = test(); // assign to l-value
    test() = t1; // error: passing 'test' as 'this' argument discards qualifiers 
}
Run Code Online (Sandbox Code Playgroud)

&在声明自定义赋值运算符重载是"唯一真正的重载方式operator="时,我不会对是否明确包含ref-qualifier提出任何意见,但是我敢于推测,那么我会猜测这样一个语句背后的意图如上所述,是 -r-value赋值的排除.

  • 我在 C++ 中花费的时间比在 C 中学习的时间要多得多。在 C 中,我学习了语法并努力研究架构,然后我就变得富有成效了。在 C++ 中,我似乎从未学习过所有语法,因此开放式问题“我什么时候才能真正高效?” 似乎总是一个不断变化的答案,只是遥不可及。 (3认同)
  • 而且……这就是 C++ 完全疯狂的原因。顺便说一句,很好的答案。 (2认同)
  • 我没听说过坎德拉,它看起来确实令人印象深刻。他们位于瑞典西海岸(斯德哥尔摩附近),而我位于东海岸(哥德堡),从事陆地运输而不是海上运输;汽车行业中安全关键的 C++ 开发(实时嵌入式/POSIX 环境中的 AD/ADAS 软件)。这通常意味着 C++ 的严格子集,这可能就是为什么我转向回答 StackOverflow 问题和工作爱好项目,以便在较少的限制下使用该语言的大部分:) (2认同)

Ada*_*ski 7

根据http://en.cppreference.com/w/cpp/language/member_functions&,您的成员函数声明 如下lvalue ref-qualifier

换句话说,它需要this是左值(隐式对象参数具有对 cv 限定的 X 的左值引用类型)。还有&&,它需要this是 r 值。

从文档复制( const、易失性和引用限定成员函数):

#include <iostream>
struct S {
  void f() & { std::cout << "lvalue\n"; }
  void f() &&{ std::cout << "rvalue\n"; }
};

int main(){
  S s;
  s.f();            // prints "lvalue"
  std::move(s).f(); // prints "rvalue"
  S().f();          // prints "rvalue"
}
Run Code Online (Sandbox Code Playgroud)