【问题标题】:Const and reference member function qualifiersconst 和 reference 成员函数限定符
【发布时间】:2020-03-24 21:04:23
【问题描述】:

假设我们有两个成员函数的成员类,定义如下:

class SomeClass
{
private:
  int val = {};
public:

  const int getVarLRef() & {
    return val;
  }
  const int getVarCLRef() const& {
    return val;
  }
};

int main()
{
  auto var1 = SomeClass().getVarCLRef();
  auto var2 = SomeClass().getVarLRef();
  return 0;
}

我不太明白const&& 之间的区别。 如果我们将此函数指定为const&,为什么它与getVarCLRef 一起工作?不应该只允许用左值调用吗?

另一方面,getVarLRef 工作正常,但在这种情况下无法按预期编译。

我使用 C++11 和 gcc 7.3.0

【问题讨论】:

  • 请注意,您的示例中的auto 转换为int,而不是int&。如果你希望它是一个引用类型,你应该改用auto&
  • 有趣的观察。我猜stackoverflow.com/questions/23011532/…stackoverflow.com/questions/21861148/… 的答案并不正确(他们中的大多数人都在谈论& 要求对象是左值)...
  • 旁注:通过 const 值返回毫无意义,无论如何都会复制该值(发生复制省略不会改变任何内容),这只会使代码更难阅读。在最坏的情况下,您只是阻止能够直接使用该对象 (x.get().foo();),但您仍然可以几乎总是(从 C++17 开始;由于 guaranteed copy elision)被 auto y = x.get(); y.foo(); 规避.

标签: c++ reference constants lvalue


【解决方案1】:

不应该只允许用左值调用吗?

因为右值也可以绑定到对const 的左值引用。就像下面的代码一样。

const SomeClass& r = SomeClass();

另一方面,右值不能绑定到非const 的左值引用,那么getVarLRef 的调用会如你所愿地失败。

【讨论】:

  • 我们不是在对象绑定到引用之前调用这个方法还是右值吗?
  • @toozyfuzzy 我不确定你的意思。理论上它与const int getVarCLRef(const SomeClass&); getVarCLRef(SomeClass{}); 相同;即将一个右值传递给将左值引用指向const的函数。
  • @toozyfuzzy 我想不出。用&&& 限定提供重载成员函数对我来说似乎更自然。
  • @toozyfuzzy 在您的具体情况下,看起来您根本不需要这些限定符,只需要 const 或什么都没有。然后将在常量对象上选择 const 版本,而在可变对象上选择另一个版本。使用 & 和 && 进行限定是有区别的:你是在左值还是右值引用上调用函数?也许您的班级可能更喜欢表现不同?
  • 假设您的函数返回一些内部缓冲区,例如。 G。 std::string。使用左值引用,您的函数可能会返回一个副本。使用右值引用,该函数可能会假设您不再需要该对象,并且它可能会将内部字符串的内容移动到返回值中,从而避免更昂贵的副本。
【解决方案2】:

常量和引用成员函数限定符能够将这些限定符应用于“this”作为常规参数,所以主要是,你有类似的东西:

int getVarLRef(SomeClass& self) { return self.val; }
int getVarCLRef(const SomeClass& self) { return self.val; }

还有,我想你知道:

getVarCLRef(SomeClass()); // Valid, temporary can bind to const lvalue reference
getVarLRef(SomeClass()); // INVALID, temporary CANNOT bind to non-const lvalue reference

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 2014-06-06
    • 2023-03-14
    • 2017-05-20
    • 1970-01-01
    • 2016-12-14
    • 1970-01-01
    相关资源
    最近更新 更多