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

参照ゲッターを提供するクラスでは、ref 修飾子のオーバーロードにより、右辺値から抽出するときに移動セマンティクスをアクティブ化できます。例えば:

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());

編集: 私は元の提案書を見つけました。それは3つの動機付けの例を提供します:

  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

1 つのユース ケースは、一時的な割り当てを禁止することです。

 // 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; }

一方、参照修飾子を使用しないと、2 つの悪い点のどちらかを選択することになります。

       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 のようには動作しません)。2 番目の選択肢は、代入を停止しますが、移動セマンティクスを排除します (たとえば、行列の乗算でパフォーマンスが低下する可能性があります)。

コメント内の @dyp によるリンクは、(左辺値または右辺値のいずれか) 参照に割り当て&&たい場合に役立つ、他の ( ) オーバーロードの使用に関する広範な議論も提供します。

于 2014-01-10T19:13:38.810 に答える
3

f() がこれのコピーであり、変更された Foo temp を必要とする場合、this代わりに temp を変更できますが、それ以外の場合は変更できません。

于 2014-01-10T19:18:13.660 に答える
0

一方では、それらを使用して、参照修飾子として追加することにより、operator=または内部状態を変更して return を返す関数など、一時的に呼び出すのが意味的に無意味な関数が呼び出されるのを防ぐことができます。void&

一方、右辺値参照がある場合、メンバーをオブジェクトから戻り値として移動するなどの最適化に使用できます。たとえば、関数は参照修飾子に応じてorgetNameを返すことができます。std::string const&std::string&&

Foo& operator+=(Foo&)別の使用例としては、代わりに右辺値参照を返すように特殊化して結果を移動可能にするなど、元のオブジェクトへの参照を返す演算子や関数が考えられます。これも最適化になります。

TL;DR: 関数の不適切な使用を防止するため、または最適化のために使用します。

于 2014-01-10T21:52:10.287 に答える