【问题标题】:What's the meaning of a prototype ending with a & (ampersand) [duplicate]以&(&符号)结尾的原型是什么意思[重复]
【发布时间】:2019-01-31 17:21:50
【问题描述】:

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

例子:

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

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

不带&的符号名称:_ZN1A2fnEv,带&_ZNR1A2fnEv

这是什么意思?我错过了什么吗?

谢谢,

【问题讨论】:

    标签: c++


    【解决方案1】:

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

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

    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() 是允许的。

    【讨论】:

    • 感谢您的解释。我以前从未见过这种语法。
    猜你喜欢
    • 2016-10-25
    • 2016-10-13
    • 2020-06-29
    • 1970-01-01
    • 1970-01-01
    • 2012-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多