27

C++11 使得基于引用限定符重载成员函数成为可能:

class Foo {
public:
  void f() &;   // for when *this is an lvalue
  void f() &&;  // for when *this is an rvalue
};

Foo obj;
obj.f();               // calls lvalue overload
std::move(obj).f();    // calls rvalue overload

我了解这是如何工作的,但它的用例是什么?

我看到N2819提议将标准库中的大多数赋值运算符限制为左值目标(即,将“ &”引用限定符添加到赋值运算符),但这被拒绝了。所以这是一个潜在的用例,委员会决定不使用它。那么,再一次,什么是合理的用例?

4

4 回答 4

21

在提供引用获取器的类中,引用限定符重载可以在从右值中提取时激活移动语义。例如:

class some_class {
  huge_heavy_class hhc;
public:
  huge_heavy_class& get() & {
    return hhc;
  }
  huge_heavy_class const& get() const& {
    return hhc;
  }
  huge_heavy_class&& get() && {
    return std::move(hhc);
  }
};

some_class factory();
auto hhc = factory().get();

这似乎确实需要付出很多努力才能获得更短的语法

auto hhc = factory().get();

具有相同的效果

auto hhc = std::move(factory().get());

编辑:我找到了原始提案文件,它提供了三个激励示例:

  1. 限制operator =为左值(TemplateRex 的回答)
  2. 为成员启用移动(基本上这个答案)
  3. 限制operator &为左值。我认为当“指针”最终被取消引用时,确保“指针”更有可能活着是明智的:
struct S {
  T operator &() &;
};

int main() {
  S foo;
  auto p1 = &foo;  // Ok
  auto p2 = &S();  // Error
}

不能说我个人曾经使用operator&过超载。

于 2014-01-10T19:49:35.753 回答
13

一种用例是禁止分配给临时工

 // can only be used with lvalues
 T& operator*=(T const& other) & { /* ... */ return *this; } 

 // not possible to do (a * b) = c;
 T operator*(T const& lhs, T const& rhs) { return lhs *= rhs; }

而不使用参考限定词会让您在两个坏处之间做出选择

       T operator*(T const& lhs, T const& rhs); // can be used on rvalues
 const T operator*(T const& lhs, T const& rhs); // inhibits move semantics

第一种选择允许移动语义,但对用户定义类型的作用与对内置类型的作用不同(不像 int 那样做)。第二种选择将停止分配但消除移动语义(例如矩阵乘法可能会影响性能)。

@dyp 在评论中的链接还提供了关于使用其他 ( ) 重载的扩展讨论,如果您想分配给(左值或右值)引用&&,这可能很有用。

于 2014-01-10T19:13:38.810 回答
3

如果 f() 需要一个 Foo 临时值,它是它的副本并已修改,您可以修改临时this值,否则不能

于 2014-01-10T19:18:13.660 回答
0

一方面,您可以使用它们通过添加作为引用限定符来防止调用在语义上无意义的函数来调用临时对象,例如operator=改变内部状态和 return的函数。void&

另一方面,您可以将其用于优化,例如当您有右值引用时将成员作为返回值移出对象,例如,函数getName可以返回 astd::string const&std::string&&取决于引用限定符。

另一个用例可能是返回对原始对象的引用的运算符和函数,例如Foo& operator+=(Foo&)可以专门返回右值引用,从而使结果可移动,这又是一种优化。

TL;DR:使用它来防止函数的错误使用或优化。

于 2014-01-10T21:52:10.287 回答