以&(&)结尾的原型的含义是什么

时间:2018-08-25 13:34:54

标签: c++

由于错误,我在原型的末尾有一个&(请参见下面的示例)。 gcc和Clang都没有抱怨。我注意到生成的符号并不完全相同。

示例:

class A
{
 public:
  void fn() &
  {
    return;
  }
};

int main()
{
  A a;
  a.fn();
  return 1;
}

不带&_ZN1A2fnEv和带&_ZNR1A2fnEv的符号名称。

是什么意思?我想念什么吗?

谢谢

1 个答案:

答案 0 :(得分:8)

成员函数声明末尾的& ref限定符。它适用于调用成员函数的对象值,并限制该值的值类别:

  • 没有引用限定符的函数可以在任何值上调用。
  • 带有&限定符的函数只能在左值上调用。
  • 带有&&限定符的函数只能在右值上调用。

ref限定符会影响重载分辨率,例如实例值不匹配的重载是不可行的。

标准库使用的引用限定符不多(我只能想到std::optional),所以让我们来编写自己的示例:

struct X {
  explicit X(int n) : s_(n, 'a') {}

  std::string s_;

  const char* f1() const    { return s_.c_str(); }
  const char* f2() const &  { return s_.c_str(); }
  const char* f3() const && { return s_.c_str(); }
};

现在考虑以下呼叫:

int main() {
  X x(10);

  x.f1();      // OK
  X(20).f1();  // OK

  x.f2();      // OK
  X(20).f2();  // ill-formed

  x.f3();      // ill-formed
  X(20).f3();  // OK
}

该示例还演示了此功能为何有用的原因:当成员函数返回对对象本身内部某些部分的引用时,重要的是,该内部引用不会超过对象的生命周期。如果您的成员函数不合格,则可以很容易地引入生命周期错误。例如:

const char* s = std::string("abcde").c_str();  // dangling pointer!

一种改进此类“内部状态访问” API的方法是为不同的ref限定的重载创建不同的返回值(类别)。要回到std::optional,参与访问本质上可以归结为这组重载:

struct MyOptional {
  T value_;  // assume engaged!

  T&  get() &  { return value_; }
  T&& get() && { return std::move(value_); }
};

这意味着MyOptional::get在左值可选上调用时返回左值,而在右值上调用时返回右值(实际上是xvalue)。这意味着,在给定MyOptional x;的情况下,允许绑定T& r = x.get();,但不允许绑定T& r = MyOptional().get();,类似地,禁止T&& r = x.get();,但允许T&& r = std::move(x).get()。 / p>