c++ 意味 参照修飾子のメンバ関数をオーバーロードするためのユースケースは何ですか?




参照 の 参照 c++ (4)

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が標準ライブラリのほとんどの代入演算子をターゲットを左辺に制限する(つまり代入演算子に " & "参照修飾子を追加する) ことを提案していましたが、 これは拒否されました 。 それは、委員会がそれに同行しないことを決めた潜在的なユースケースでした。 だから、合理的なユースケースは何ですか?


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

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

もう1つのユースケースは、 Foo& operator+=(Foo&)ような元のオブジェクトへの参照を返す演算子と関数です。代わりにrvalue参照を返すように特殊化でき、結果を移動可能にします。

TL; DR:誤った機能の使用や最適化を防ぐために使用します。


参照ゲッターを提供するクラスでは、ref-qualifierオーバーロードは、rvalueから抽出するときに移動セマンティクスを有効にすることができます。 例えば:

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 & lvaluesに制限する。 私は、 "ポインタ"が最終的に参照解除されたときに、 "ポインティ(pointee)"が生きている可能性が高いことを確実にするのは賢明だと思います。
struct S {
  T operator &() &;
};

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

私は個人的にoperator&使用してoperator&オーバーロードを言うことはできません。


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によるリンクも、(lvalueまたはrvalueのいずれかの)参照を割り当てる場合に便利な、もう一方の( && )オーバーロードの使用に関する拡張された議論を提供します。


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





qualifiers