本文介绍了&是什么(“&”号)成员函数签名的末尾是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不记得是哪个话题,但是最近我看了CppCon 2017的一些谈话,有人在旁注中提到,重载<$的唯一 true 方法c $ c> operator = 的格式如下:

I can't remember which talk it was, but recently I watched some talks from CppCon 2017 and there someone mentioned as some kind of side-note, that the only true way of overloading operator= would be in the following fashion:

class test {
public:
    test& operator=(const test&) &;
};

他明确强调了结尾的& ,但

He explicitly emphasized the trailing & but didn't say what it does.

那么它做什么呢?

推荐答案

Ref限定词-在C ++ 11中引入



Ref限定词不是C ++ 17的功能(看问题的标签),但是是C ++ 11中引入的功能。

Ref-qualifiers - introduced in C++11

Ref-qualifiers is not C++17 feature (looking at the tag of the question), but was a feature introduced in 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();         // [prvalue] const rvalue Foo
  Foo().bar();            // [prvalue] rvalue Foo

  // xvalues bind to rvalue references, and overload resolution
  // favours selecting the rvalue ref-qualifier overloads.
  std::move(c_foo).bar(); // [xvalue] const rvalue Foo
  std::move(foo).bar();   // [xvalue] rvalue Foo
}

请注意,右值可用于初始化一个const左值引用(并以此扩展由右值标识的对象的生存期),这意味着,如果我们从上例中删除右值ref-qualifier重载,则该示例中的右值类别将全部支持其余的 const& 重载:

Note that an rvalue may be used to initialize a const lvalue reference (and in so expanding the lifetime of the object identified by the rvalue), meaning that if we remove the rvalue ref-qualifier overloads from the example above, then the rvalue value categories in the example will all favour the remaining const & overload:

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

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

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

  // For all rvalue value categories overload resolution
  // now selects the 'const &' overload, as an rvalue may
  // be used to initialize a const lvalue reference.
  c_foo.bar();            // const lvalue Foo
  foo.bar();              // lvalue Foo
  getFoo().bar();         // const lvalue Foo
  Foo().bar();            // const lvalue Foo
  std::move(c_foo).bar(); // const lvalue Foo
  std::move(foo).bar();   // const lvalue Foo
}

参见例如以下博客文章以作简要介绍:

See e.g. the following blog post for for a brief introduction:



  • Andrzej's C++ blog - Ref-qualifiers

为了可能解释您从CppCon对话中收集的报价的意图,

To possibly explain the intent of your recollected quote from the CppCon talk,

请访问 [强调我的]:

we visit [over.match.funcs]/1, /4 & /5 [emphasis mine]:

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

/4 For non-static member functions, the type of the implicit object parameter is


  • (4.1)—对cv X 的左值引用,对于声明为且没有引用的函数-qualifier或带有 & ref-qualifier

  • (4.1) — "lvalue reference to cv X" for functions declared without a ref-qualifier or with the & ref-qualifier

(4.2)—对使用&& ref-qualifier

(4.2) — "rvalue reference to cv X" for functions declared with the && ref-qualifier

其中, X 是该函数是成员的类,而cv是
成员函数声明中的cv-qualification。 ...

where X is the class of which the function is a member and cv is the cv-qualification on the member function declaration. ...

/ 5 ...对于声明为没有引用限定符的非静态成员函数,将应用附加规则:

/5 ... For non-static member functions declared without a ref-qualifier, an additional rule applies:


  • (5.1)-即使隐式对象参数不是const限定的,右值也可以是只要在所有其他方面都可以将
    绑定到该参数,则可以将该参数转换为
    隐式对象参数的类型。
    [注:这样的参数是$ b $的事实b右值不影响隐式转换
    序列的排名。 — end note]

  • (5.1) — even if the implicit object parameter is not const-qualified, an rvalue can be bound to the parameter as long as in all other respects the argument can be converted to the type of the implicit object parameter. [ Note: The fact that such an argument is an rvalue does not affect the ranking of implicit conversion sequences. — end note ]

从上面的/ 5开始,以下重载(其中显式& ref限定词已省略)

From /5 above, the following overload (where the explicit & ref-qualifier has been omitted)

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

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

allows assigning values to r-values, e.g.

int main()
{
    test t1;
    t1 = test(); // assign to l-value
    test() = t1; // assign to r-value
}

但是,如果我们用& ref限定词不适用,只要我们不提供&& 引用声明的重载即可

However, if we explicitly declare the overload with the & ref-qualifier, [over.match.funcs]/5.1 does not apply, and as long we do not supply an overload declared with the && ref-qualifier, r-value assignment will not be allowed.

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

int main()
{
    test t1;
    t1 = test(); // assign to l-value
    test() = t1; // error [clang]: error: no viable overloaded '='
}

I声明自定义赋值运算符重载是否为时,对于是否显式包括& ref限定符不会发表任何意见 $ c> operator = ,但是我敢于推测,然后我猜想这样声明的意图是排除 to -r值赋值。

I won't place any opinion as to whether explicitly including the & ref-qualifier when declaring custom assignment operator overloads is "the only true way of overload operator=", but would I dare to speculate, then I would guess that the intent behind such a statement is the exclusion of to-r-value assignment.

作为设计合理的赋值运算符,可以说永远不要是 const const T&运算符=(const T&)const& 并没有多大意义),并且由于右值不能用于初始化非常量左值引用,因此一组给定类型 T operator = 重载,其中仅包含 T& operator =(const T&)& 永远不会提供可行的重载,该重载可以从标识为右值的 T 对象调用类别。

As a properly designed assignment operator should arguably never be const (const T& operator=(const T&) const & would not make much sense), and as an rvalue may not be used to initialize a non-const lvalue reference, a set of overloads for operator= for a given type T that contain only T& operator=(const T&) & will never proviade a viable overload that can be invoked from a T object identified to be of an rvalue value category.

这篇关于&amp;是什么(“&”号)成员函数签名的末尾是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 18:55