c++ - 実装 - 本の虫 rvalue




「* thisの右辺値参照」とは何ですか? (2)

clangのC ++ 11ステータスページで 「* thisのための右辺値参照」という提案に出会いました。

右辺値参照についてかなり読んで理解しましたが、私はこれについて知っているとは思いません。 私はまた、その用語を使ってウェブ上で多くのリソースを見つけることができませんでした。

このページにプロポーザルのペーパーへのリンクがあります: N2439 (* move semanticsを* thisに拡張する)、しかし私はそこから多くの例を得ていない。

この機能は何ですか?


クラスに2つの関数があり、両方とも同じ名前とシグネチャを持つとしましょう。 しかし、そのうちの1つはconstとして宣言されています。

void SomeFunc() const;
void SomeFunc();

クラスインスタンスがconstではない場合、オーバーロード解決は非constバージョンを優先的に選択します。 インスタンスがconst場合、ユーザーはconstバージョンのみを呼び出すことができます。 thisポインタはconstポインタなので、インスタンスは変更できません。

これに対するr値の参照は、別の選択肢を追加することを可能にします。

void RValueFunc() &&;

これにより、ユーザーが適切なr値を介してそれを呼び出す場合にのみ呼び出すことができる関数を持つことができます。 これがObject型の場合

Object foo;
foo.RValueFunc(); //error: no `RValueFunc` version exists that takes `this` as l-value.
Object().RValueFunc(); //calls the non-const, && version.

このようにして、オブジェクトがr値を介してアクセスされているかどうかに基づいて動作を特殊化することができます。

r値参照バージョンと非参照バージョンの間ではオーバーロードできません。 つまり、メンバー関数名がある場合、そのすべてのバージョンはこれにl / r-value修飾子を使用するか、または使用しません。 これはできません。

void SomeFunc();
void SomeFunc() &&;

あなたはこれをしなければなりません:

void SomeFunc() &;
void SomeFunc() &&;

この宣言によって*thisの型が変わることに注意してください。 これは、 &&バージョンがすべてr値参照としてメンバーにアクセスすることを意味します。 そのため、オブジェクト内から簡単に移動することが可能になります。 プロポーザルの最初のバージョンで示されている例は次のとおりです(注:以下はC ++ 11の最終バージョンでは正しくない場合があります。これは最初のプロポーザルの "r-value"プロポーザルから直接です)。

class X {
   std::vector<char> data_;
public:
   // ...
   std::vector<char> const & data() const & { return data_; }
   std::vector<char> && data() && { return data_; }
};

X f();

// ...
X x;
std::vector<char> a = x.data(); // copy
std::vector<char> b = f().data(); // move

左辺値参照修飾子形式のための追加のユースケースがあります。 C ++ 98には、右辺値であるクラスインスタンスに対して非constメンバ関数を呼び出すことを許可する言語があります。 これは、rvaluenessの概念そのものに反し、組み込み型がどのように機能するかから逸脱する、あらゆる種類の奇妙さにつながります。

struct S {
  S& operator ++(); 
  S* operator &(); 
};
S() = S();      // rvalue as a left-hand-side of assignment!
S& foo = ++S(); // oops, dangling reference
&S();           // taking address of rvalue...

左辺値修飾子はこれらの問題を解決します。

struct S {
  S& operator ++() &;
  S* operator &() &;
  const S& operator =(const S&) &;
};

これで、演算子は左辺値のみを受け入れて、組み込み型の演算子のように機能します。







qualifiers