右辺値、左辺値、x値、glvalue、およびprvalueとは何ですか?

1413
James McNellis 2010-08-31 05:02.

C ++ 03では、式は右辺値または左辺値のいずれかです。

C ++ 11では、式は次のようになります。

  1. 右辺値
  2. 左辺値
  3. xvalue
  4. glvalue
  5. prvalue

2つのカテゴリが5つのカテゴリになりました。

  • これらの新しい表現のカテゴリは何ですか?
  • これらの新しいカテゴリは、既存の右辺値および左辺値のカテゴリとどのように関連していますか?
  • C ++ 0xの右辺値と左辺値のカテゴリは、C ++ 03の場合と同じですか?
  • これらの新しいカテゴリが必要なのはなぜですか?WG21の神々は、私たちを単なる人間と混同しようとしているだけですか?

11 answers

655
Kornel Kisielewicz 2010-08-31 05:09.

このドキュメントはそれほど短い紹介ではないかもしれません:n3055

虐殺全体は、移動のセマンティクスから始まりました。移動できる式とコピーできない式ができたら、突然ルールを把握しやすくなり、移動できる式とその方向を区別する必要がありました。

ドラフトに基づいて私が推測することから、r / l値の区別は同じままですが、物事を動かすという状況でのみ混乱します。

それらは必要ですか?新しい機能を失いたいのであれば、おそらくそうではありません。しかし、より良い最適化を可能にするために、おそらくそれらを受け入れる必要があります。

n3055の引用:

  • 左辺値は、(いわゆる、歴史的に、左辺値が代入式の左側に表示されなかったため)関数またはオブジェクトを指定します。[例:Eがポインタ型の式である場合、*Eはが指すオブジェクトまたは関数を参照する左辺値式Eです。別の例として、戻り値の型が左辺値参照である関数を呼び出した結果は左辺値です。]
  • xValue(「期限切れ」値)も(そのリソースは、例えば、移動させることができるように)通常、その寿命の終わり近くに、オブジェクトを指します。xvalueは、右辺値参照を含む特定の種類の式の結果です。[例:戻り値の型が右辺値参照である関数を呼び出した結果はxvalueです。]
  • glvalue(「一般化」左辺値)は左辺値はxValue
  • 右辺値は、(いわゆる、歴史的に、右辺値が代入式の右側に表示される可能性があるため)はxValue、一時オブジェクトまたはそのサブオブジェクト、またはオブジェクトに関連付けられていない値です。
  • prvalue(「純粋な」右辺)がはxValueない右辺値です。[例:戻り値の型が参照ではない関数を呼び出した結果はprvalueです]

問題のドキュメントは、新しい命名法の導入の結果として発生した標準の正確な変更を示しているため、この質問の優れたリファレンスです。

345
dirkgently 2010-08-31 05:18.

これらの新しい表現のカテゴリは何ですか?

FCD(n3092)は優れた記述を有します。

—左辺値(左辺値は代入式の左側に表示される可能性があるため、歴史的には呼ばれます)は、関数またはオブジェクトを指定します。[例:Eがポインター型の式である場合、* EはEが指すオブジェクトまたは関数を参照する左辺値式です。別の例として、戻り値の型が左辺値参照である関数を呼び出した結果は左辺値です。—例を終了]

— xvalue(「eXpiring」値)は、通常、その存続期間の終わり近くにあるオブジェクトを参照します(たとえば、そのリソースを移動できるようにするため)。xvalueは、右辺値参照を含む特定の種類の式の結果です(8.3.2)。[例:戻り値の型が右辺値参照である関数を呼び出した結果はxvalueです。—例を終了]

— glvalue(「一般化された」左辺値)は左辺値またはx値です。

—右辺値(歴史的には、右辺値が代入式の右側に表示される可能性があるため、いわゆる)は、x値、一時オブジェクト(12.2)またはそのサブオブジェクト、またはオブジェクトに関連付けられていない値です。

— prvalue(「純粋な」右辺値)は、x値ではない右辺値です。[例:戻り値の型が参照ではない関数を呼び出した結果は、prvalueです。12、7.3e5、またはtrueなどのリテラルの値もprvalueです。—例を終了]

すべての式は、この分類法の基本的な分類の1つ、つまり左辺値、x値、またはprvalueに属します。式のこのプロパティは、その値カテゴリと呼ばれます。[注:第5節の各組み込み演算子の説明は、それが生成する値のカテゴリーと、それが期待するオペランドの値カテゴリーを示しています。たとえば、組み込みの代入演算子は、左のオペランドが左辺値であり、右のオペランドが左辺値であり、結果として左辺値を生成することを想定しています。ユーザー定義の演算子は関数であり、それらが期待して生成する値のカテゴリは、パラメーターと戻り値の型によって決定されます。—エンドノート

ただし、セクション3.10の左辺値と右辺値全体を読むことをお勧めします。

これらの新しいカテゴリは、既存の右辺値および左辺値のカテゴリとどのように関連していますか?

再び:

C ++ 0xの右辺値と左辺値のカテゴリは、C ++ 03の場合と同じですか?

右辺値のセマンティクスは、特に移動セマンティクスの導入によって進化しました。

これらの新しいカテゴリが必要なのはなぜですか?

そのため、移動の構築/割り当てを定義してサポートすることができます。

193
sellibitze 2010-08-31 22:08.

最後の質問から始めましょう:

これらの新しいカテゴリが必要なのはなぜですか?

C ++標準には、式の値カテゴリを処理する多くのルールが含まれています。一部のルールでは、左辺値と右辺値を区別しています。たとえば、過負荷の解決に関しては。他のルールは、glvalueとprvalueを区別します。たとえば、不完全または抽象型のglvalueを持つことができますが、不完全または抽象型のprvalueはありません。この用語を使用する前は、lvalue / rvalueを参照するglvalue / prvalueを実際に区別する必要のあるルールは、意図せず間違っているか、ルールの説明と例外が多く含まれていました。ただし、rvalueが名前のないものである場合を除きます。右辺値参照...」。したがって、glvaluesとprvaluesの概念に独自の名前を付けるのは良い考えのようです。

これらの新しい表現のカテゴリは何ですか?これらの新しいカテゴリは、既存の右辺値および左辺値のカテゴリとどのように関連していますか?

C ++ 98と互換性のある左辺値と右辺値という用語がまだあります。右辺値をxvaluesとprvaluesの2つのサブグループに分割し、左辺値とxvaluesをglvaluesと呼びます。Xvaluesは、名前のない右辺値参照の新しい種類の値カテゴリです。すべての式は、左辺値、x値、prvalueの3つのいずれかです。ベン図は次のようになります。

    ______ ______
   /      X      \
  /      / \      \
 |   l  | x |  pr  |
  \      \ /      /
   \______X______/
       gl    r

関数の例:

int   prvalue();
int&  lvalue();
int&& xvalue();

ただし、名前付き右辺値参照は左辺値であることも忘れないでください。

void foo(int&& t) {
  // t is initialized with an rvalue expression
  // but is actually an lvalue expression itself
}
173
Nicol Bolas 2012-03-04 20:32.

これらの新しいカテゴリが必要なのはなぜですか?WG21の神々は、私たちを単なる人間と混同しようとしているだけですか?

他の答え(それらの多くは良いですが)がこの特定の質問に対する答えを実際に捉えているとは思いません。はい、これらのカテゴリなどは移動セマンティクスを可能にするために存在しますが、複雑さは1つの理由で存在します。これは、C ++ 11での移動に関する1つの違反ルールです。

あなたはそうすることが間違いなく安全であるときだけ動くべきです。

そのため、これらのカテゴリが存在します。それらから移動しても安全な値について話すことができ、そうでない場所で値について話すことができます。

r値参照の初期バージョンでは、移動は簡単に発生しました。簡単すぎる。簡単に言えば、ユーザーが本当に意図していなかったときに、暗黙のうちに物を動かす可能性がたくさんありました。

何かを移動しても安全な状況は次のとおりです。

  1. それが一時的またはそのサブオブジェクトである場合。(prvalue)
  2. ユーザーが明示的に移動するように言ったとき

これを行う場合:

SomeType &&Func() { ... }

SomeType &&val = Func();
SomeType otherVal{val};

これは何をしますか?仕様の古いバージョンでは、5つの値が入る前に、これは動きを引き起こしました。もちろんそうです。コンストラクターに右辺値参照を渡したため、右辺値参照を受け取るコンストラクターにバインドされます。それは明らかです。

これには1つだけ問題があります。あなたはそれを動かすように頼まなかった。ああ、あなたはそれが&&手がかりであるべきだったと言うかもしれません、しかしそれはそれが規則を破ったという事実を変えません。val一時的なものには名前がないため、一時的なものではありません。一時的なものの寿命を延ばしたかもしれませんが、それは一時的なものではないことを意味します。他のスタック変数と同じです。

それが一時的なものではなく、移動を要求しなかった場合、移動は間違っています。

明らかな解決策はval、左辺値を作成することです。これは、そこから移動できないことを意味します。いいよ; 名前が付けられているので、左辺値です。

SomeType&&そうすると、それがどこでも同じことを意味するとは言えなくなります。これで、名前付き右辺値参照と名前なし右辺値参照を区別できました。名前付き右辺値参照は左辺値です。それが上記の解決策でした。では、名前のない右辺値参照(Func上記からの戻り値)を何と呼びますか?

左辺値から移動できないため、左辺値ではありません。そして、;を返すことで移動できる必要があり&&ます。他にどのように何かを動かすと明示的に言うことができますか?std::move結局のところ、それが戻ってきます。方程式の左側にある可能性があるため、右辺値(古いスタイル)ではありません(実際には少し複雑です。この質問と以下のコメントを参照してください)。左辺値でも右辺値でもありません。それは新しい種類のものです。

私たちが持っているのは、暗黙的に移動可能であることを除いて、左辺値として扱うことができる値です。これをxvalueと呼びます。

xvaluesは、他の2つのカテゴリの値を取得する理由であることに注意してください。

  • prvalueは、実際には前のタイプの右辺値の新しい名前です。つまり、xvaluesではない右辺値です。

  • Glvaluesは、多くの共通のプロパティを共有するため、1つのグループ内のxvaluesとlvaluesの和集合です。

つまり、実際には、すべてxvaluesと、移動を正確に特定の場所にのみ制限する必要があります。これらの場所は、右辺値カテゴリによって定義されます。prvaluesは暗黙的な移動であり、xvaluesは明示的な移動です(std::movexvalueを返します)。

142
Ivan Kush 2016-07-04 02:30.

IMHO、その意味について最良の説明は、私たち与えたStroustrup氏のアカウントの例に+テイクをダニエル・シャーンドルとモハン:

Stroustrup:

今、私は真剣に心配していました。明らかに、私たちは行き詰まりまたは混乱、あるいはその両方に向かっていました。昼食時に分析を行って、(値の)どのプロパティが独立しているかを確認しました。独立したプロパティは2つしかありませんでした。

  • has identity –つまり、アドレス、ポインタ、ユーザーは2つのコピーが同一であるかどうかを判断できます。
  • can be moved from –つまり、不確定であるが有効な状態で「コピー」のソースに任せることが許可されています

これにより、正確に3種類の値があるという結論に至りました(大文字を使用して負の値を示す正規表現のトリックを使用-私は急いでいました):

  • iM:アイデンティティがあり、から移動することはできません
  • im:アイデンティティがあり、から移動できます(たとえば、左辺値を右辺値参照にキャストした結果)
  • Im:IDがなく、から移動できます。

    4番目の可能性でIMある(アイデンティティがなく、移動できないC++)は、他の言語では役に立ちません(または、私は思います)。

これらの3つの基本的な値の分類に加えて、2つの独立したプロパティに対応する2つの明らかな一般化があります。

  • i:アイデンティティを持っている
  • m:から移動できます

これにより、私はこの図をボードに載せました。

ネーミング

名前を付ける自由が限られていることに気づきました。左側の2つのポイント(ラベルiMi)は、多かれ少なかれ形式的な人々が呼んlvaluesでいるものでmあり、右側の2つのポイント(ラベル付きとIm)は、多かれ少なかれ形式的な人々が呼んでいるものです。と呼ばれていrvaluesます。これは私たちの命名に反映されなければなりません。つまり、の左側の「レッグ」にはW関連する名前がlvalueあり、右側の「レッグ」にはW関連する名前があるはずrvalue.です。この議論/問題全体は、右辺値参照と移動セマンティクスの導入から生じることに注意してください。これらの概念は、ちょうどrvaluesとで構成されるStracheyの世界には存在しませんlvalues。誰かがそのアイデアを観察しました

  • すべてはvalueどちらかですlvaluervalue
  • Anがlvalueないrvaluervalueできませんlvalue

私たちの意識、非常に有用な特性に深く埋め込まれており、この二分法の痕跡はドラフト標準全体に見られます。私たちは皆、それらの特性を保存する(そしてそれらを正確にする)べきであることに同意しました。これにより、名前の選択がさらに制限されました。私は、標準ライブラリの表現が(一般化)rvalueを意味するために使用することを観察しました。そのため、標準ライブラリmの期待値とテキストを保持するには、の右下の点にW名前を付ける必要があります。rvalue.

これは、ネーミングの焦点を絞った議論につながりました。まず、意味するlvalue.べきか、一般化lvalueするべきかを決定する必要がありました。Doug Gregorが率いる私たちは、コア言語の文言で、その単語がどちらか一方を意味するように修飾されている場所をリストしました。リストが作成され、ほとんどの場合、最もトリッキーで壊れやすいテキストでは、現在、を意味します。「昔」は何も動かされなかったので、これは左辺値の古典的な意味です。の新しい概念です。また、のTOPLEFTポイントを命名することは、すべての値であることを私たちに財産を与えるか、その両方ではなく。iMilvaluelvalueiMmoveC++0xW lvaluelvaluervalue

だから、の左上の点がWあるlvalueと右下の点があるrvalue.ことが左下と右上のポイントを作るんか?左下の点は、移動を可能にする古典的な左辺値の一般化です。だからそれはgeneralized lvalue.私たちがそれを名付けたものglvalue.ですあなたは略語について口論することができますが、(私は思う)論理ではありません。generalized lvalueとにかく真面目な使い方はなんとなく省略されると思いましたので、すぐにやったほうがいいです(混乱のリスクがあります)。Wの右上の点は、右下の点よりも一般的ではありません(現在は相変わらずと呼ばれていますrvalue)。そのポイントは、(デストラクタを除いて)再度参照できないため、移動できるオブジェクトの元の純粋な概念を表しています。私は、フレーズ気に入ったspecialized rvalueとは対照的にするgeneralized lvalueが、pure rvalue略称prvalue(そしておそらく当然のように)勝ちました。したがって、Wの左脚はlvalueandでglvalueあり、右脚はprvalueandです。rvalue.ちなみに、すべての値はglvalueまたはprvalueのいずれかですが、両方ではありません。

これにより、Wim;の上部中央が残ります。つまり、アイデンティティを持ち、移動できる値です。それらの難解な獣の良い名前に私たちを導くものは本当にありません。これらは(ドラフト)標準テキストを扱う人々にとって重要ですが、一般的な名前になる可能性は低いです。私たちを導くための命名に関する実際の制約は見つからなかったので、中心、未知、奇妙、xpertのみ、またはx-ratedに「x」を選択しました。

64
Dániel Sándor 2016-01-21 03:46.

前書き

ISOC ++ 11(正式にはISO / IEC 14882:2011)は、C ++プログラミング言語の標準の最新バージョンです。これには、次のようないくつかの新機能と概念が含まれています。

  • 右辺値参照
  • xvalue、glvalue、prvalue式の値のカテゴリ
  • 移動セマンティクス

新しい式の値のカテゴリの概念を理解したい場合は、右辺値と左辺値の参照があることに注意する必要があります。右辺値を非定数右辺値参照に渡すことができることを知っておくとよいでしょう。

int& r_i=7; // compile error
int&& rr_i=7; // OK

作業ドラフトN3337(公開されたISOC ++ 11標準に最も類似したドラフト)からLvalues and rvaluesというタイトルのサブセクションを引用すると、値カテゴリの概念についてある程度の直感を得ることができます。

3.10左辺値と右辺値[basic.lval]

1式は、図1の分類法に従って分類されています。

  • 左辺値(左辺値は代入式の左側に表示される可能性があるため、歴史的には呼ばれます)は、関数またはオブジェクトを指定します。[例:Eがポインター型の式である場合、* EはEが指すオブジェクトまたは関数を参照する左辺値式です。別の例として、戻り値の型が左辺値参照である関数を呼び出した結果は左辺値です。—例を終了]
  • xvalue(「eXpiring」値)は、通常、その存続期間の終わり近くにあるオブジェクトを参照します(たとえば、そのリソースを移動できるようにするため)。xvalueは、右辺値参照を含む特定の種類の式の結果です(8.3.2)。[例:戻り値の型が右辺値参照である関数を呼び出した結果はxvalueです。—例を終了]
  • glvalue(「一般化された」左辺値)は左辺値またはx値です。
  • 右辺値(歴史的には、右辺値が代入式の右側に表示される可能性があるため、いわゆる)は、x値、
    一時オブジェクト(12.2)またはそのサブオブジェクト、または
    オブジェクトに関連付けられていない値です。
  • prvalue(「純粋な」右辺値)は、x値ではない右辺値です。[例:戻り値の型が
    参照ではない関数を呼び出した結果は、prvalueです。12、7.3e5、または
    trueなどのリテラルの値もprvalueです。—例を終了]

すべての式は、この分類法の基本的な分類の1つ、つまり左辺値、x値、またはprvalueに属します。式のこのプロパティは、その値カテゴリと呼ばれます。

しかし、このサブセクションが概念を明確に理解するのに十分であるかどうかはよくわかりません。「通常」は実際には一般的ではなく、「寿命の終わり近く」は実際には具体的ではなく、「戻り値の参照を含む」は実際には明確ではないためです。および「例:戻り値の型が右辺値参照である関数を呼び出した結果はx値です。」ヘビが尻尾を噛んでいるように聞こえます。

一次価値カテゴリー

すべての式は、1つのプライマリ値カテゴリに属します。これらの値のカテゴリは、左辺値、x値、およびprvalueのカテゴリです。

左辺値

式Eは、EがEの外部からアクセスできるようにするID(アドレス、名前、またはエイリアス)をすでに持っているエンティティを参照する場合にのみ、左辺値カテゴリに属します。

#include <iostream>

int i=7;

const int& f(){
    return i;
}

int main()
{
    std::cout<<&"www"<<std::endl; // The expression "www" in this row is an lvalue expression, because string literals are arrays and every array has an address.  

    i; // The expression i in this row is an lvalue expression, because it refers to the same entity ...
    i; // ... as the entity the expression i in this row refers to.

    int* p_i=new int(7);
    *p_i; // The expression *p_i in this row is an lvalue expression, because it refers to the same entity ...
    *p_i; // ... as the entity the expression *p_i in this row refers to.

    const int& r_I=7;
    r_I; // The expression r_I in this row is an lvalue expression, because it refers to the same entity ...
    r_I; // ... as the entity the expression r_I in this row refers to.

    f(); // The expression f() in this row is an lvalue expression, because it refers to the same entity ...
    i; // ... as the entity the expression f() in this row refers to.

    return 0;
}

xvalues

式Eは、次の場合にのみxvalueカテゴリに属します。

—暗黙的または明示的に、戻り値の型が返されるオブジェクトの型への右辺値参照である関数を呼び出した結果、または

int&& f(){
    return 3;
}

int main()
{
    f(); // The expression f() belongs to the xvalue category, because f() return type is an rvalue reference to object type.

    return 0;
}

—オブジェクトタイプへの右辺値参照へのキャスト、または

int main()
{
    static_cast<int&&>(7); // The expression static_cast<int&&>(7) belongs to the xvalue category, because it is a cast to an rvalue reference to object type.
    std::move(7); // std::move(7) is equivalent to static_cast<int&&>(7).

    return 0;
}

—オブジェクト式がxvalueである、非参照タイプの非静的データメンバーを指定するクラスメンバーアクセス式、または

struct As
{
    int i;
};

As&& f(){
    return As();
}

int main()
{
    f().i; // The expression f().i belongs to the xvalue category, because As::i is a non-static data member of non-reference type, and the subexpression f() belongs to the xvlaue category.

    return 0;
}

—第1オペランドがx値で、第2オペランドがデータメンバーへのポインタである、メンバーへのポインタ式。

上記のルールの効果は、オブジェクトへの名前付き右辺値参照が左辺値として扱われ、オブジェクトへの名前なし右辺値参照がx値として扱われることです。関数への右辺値参照は、名前が付けられているかどうかに関係なく、左辺値として扱われます。

#include <functional>

struct As
{
    int i;
};

As&& f(){
    return As();
}

int main()
{
    f(); // The expression f() belongs to the xvalue category, because it refers to an unnamed rvalue reference to object.
    As&& rr_a=As();
    rr_a; // The expression rr_a belongs to the lvalue category, because it refers to a named rvalue reference to object.
    std::ref(f); // The expression std::ref(f) belongs to the lvalue category, because it refers to an rvalue reference to function.

    return 0;
}

prvalues

式Eは、Eが左辺値にもx値カテゴリにも属していない場合に限り、prvalueカテゴリに属します。

struct As
{
    void f(){
        this; // The expression this is a prvalue expression. Note, that the expression this is not a variable.
    }
};

As f(){
    return As();
}

int main()
{
    f(); // The expression f() belongs to the prvalue category, because it belongs neither to the lvalue nor to the xvalue category.

    return 0;
}

混合値のカテゴリ

さらに2つの重要な混合値カテゴリがあります。これらの値カテゴリは、右辺値と左辺値のカテゴリです。

右辺値

式Eは、Eがxvalueカテゴリ、またはprvalueカテゴリに属している場合に限り、右辺値カテゴリに属します。

この定義は、EがE YETの外部でアクセスできるようにするIDを持たないエンティティを参照する場合にのみ、式Eが右辺値カテゴリに属する​​ことを意味することに注意してください。

glvalues

式Eは、Eが左辺値カテゴリまたはx値カテゴリに属している場合に限り、glvalueカテゴリに属します。

実用的なルール

スコット・マイヤーはしている出版さ左辺値から右辺値を区別するために親指の非常に便利なルールを。

  • 式のアドレスを取得できる場合、その式は左辺値です。
  • 式のタイプが左辺値参照(たとえば、T&またはconst T&など)である場合、その式は左辺値です。
  • それ以外の場合、式は右辺値です。概念的に(そして通常は実際にも)、右辺値は、関数から返されるオブジェクトや暗黙的な型変換によって作成されるオブジェクトなどの一時オブジェクトに対応します。ほとんどのリテラル値(たとえば、10および5.3)も右辺値です。
35
Johannes Schaub - litb 2010-08-31 06:46.

C ++ 03のカテゴリは制限が多すぎて、式属性への右辺値参照の導入を正しくキャプチャできません。

それらの導入により、名前のない右辺値参照は右辺値に評価されるため、オーバーロード解決では右辺値参照バインディングが優先され、コピーコンストラクターよりも移動コンストラクターが選択されると言われていました。しかし、これは、たとえば動的タイプや資格など、あらゆる面で問題を引き起こすことが判明しました。

これを示すために、

int const&& f();

int main() {
  int &&i = f(); // disgusting!
}

xvalueより前のドラフトでは、これが許可されていました。これは、C ++ 03では、クラス以外の型の右辺値がcv修飾されないためです。ただしconst、ここでオブジェクト(=メモリ!)を参照しているため、右辺値参照の場合に適用することを目的としています。クラス以外の右辺値からconstを削除するのは、主に周囲にオブジェクトがないためです。

動的型の問題も同様の性質です。C ++ 03では、クラス型の右辺値には既知の動的型があります。これは、その式の静的型です。別の方法で使用するには、左辺値に評価される参照または逆参照が必要です。名前のない右辺値参照には当てはまりませんが、ポリモーフィックな動作を示す可能性があります。だからそれを解決するために、

  • 名前のない右辺値参照はxvaluesになります。それらは修飾することができ、潜在的に動的タイプが異なる可能性があります。それらは、意図したように、オーバーロード中に右辺値参照を優先し、非定数左辺値参照にバインドしません。

  • 以前は右辺値(リテラル、非参照型へのキャストによって作成されたオブジェクト)であったものが、今ではprvalueになります。それらは、オーバーロード中のxvaluesと同じ優先順位を持っています。

  • 以前は左辺値でしたが、左辺値のままです。

二つのグループは、修飾することができるものをキャプチャするために行われ、異なる動的タイプ(持つことができglvalues)と過負荷が(結合右辺値リファレンスを好む場合、それらの右辺値を)。

29
Felix Dombek 2016-06-17 16:20.

値のカテゴリのcppreference.comの説明に出くわすまで、私は長い間これに苦労してきました。

実はかなりシンプルですが、覚えにくい説明が多いようです。ここでは、非常に概略的に説明されています。ページの一部を引用します。

主なカテゴリ

主要な値のカテゴリは、式の2つのプロパティに対応します。

  • アイデンティティを持っている:オブジェクトのアドレスまたはオブジェクトが識別する関数(直接または間接的に取得)を比較するなどして、式が別の式と同じエンティティを参照しているかどうかを判断できます。

  • から移動できます:moveコンストラクター、move割り当て演算子、またはmoveセマンティクスを実装する別の関数オーバーロードを式にバインドできます。

次のような表現:

  • アイデンティティを持ち、そこから移動できないことを左辺値式と呼びます。
  • アイデンティティを持ち、そこから移動できることをxvalue式呼びます
  • アイデンティティを持たず、移動できるのはprvalue式と呼ばれます。
  • アイデンティティがなく、移動できないものは使用されません。

左辺値

左辺値(「左値」)式は、アイデンティティ持ちから移動できない式です。

rvalue(C ++ 11まで)、prvalue(C ++ 11以降)

prvalue(「純粋右辺値」)の式は式であるアイデンティティを持っていない移動でき

xvalue

xvalue( "expiring value")式は、アイデンティティ持ちから移動できる式です。

glvalue

glvalue( "generalized lvalue")式は、左辺値またはx値のいずれかである式です。それはアイデンティティを持っています。から移動される場合とされない場合があります。

右辺値(C ++ 11以降)

右辺値(「右値」)式は、prvalueまたはxvalueのいずれかである式です。これは、から移動することができます。アイデンティティがある場合とない場合があります。

19
fredoverflow 2010-08-31 05:45.

これらの新しいカテゴリは、既存の右辺値および左辺値のカテゴリとどのように関連していますか?

C ++ 03左辺値は引き続きC ++ 11左辺値ですが、C ++ 03右辺値はC ++ 11ではprvalueと呼ばれます。

17
thebrandre 2019-02-15 06:10.

前の回答は価値カテゴリの背後にある理論を徹底的にカバーしていたので、私が追加したいもう1つのことがあります。実際にそれを試してテストすることができます。

値のカテゴリを実際に試す場合は、decltype指定子を使用できます。その動作は、3つの主要な値のカテゴリ(xvalue、lvalue、およびprvalue)を明示的に区別します。

プリプロセッサを使用すると、入力の手間が省けます...

主なカテゴリ:

#define IS_XVALUE(X) std::is_rvalue_reference<decltype((X))>::value
#define IS_LVALUE(X) std::is_lvalue_reference<decltype((X))>::value
#define IS_PRVALUE(X) !std::is_reference<decltype((X))>::value

混合カテゴリ:

#define IS_GLVALUE(X) (IS_LVALUE(X) || IS_XVALUE(X))
#define IS_RVALUE(X) (IS_PRVALUE(X) || IS_XVALUE(X))

これで、値カテゴリのcppreferenceから(ほぼ)すべての例を再現できます。

C ++ 17の例を次に示します(簡潔なstatic_assertの場合)。

void doesNothing(){}
struct S
{
    int x{0};
};
int x = 1;
int y = 2;
S s;

static_assert(IS_LVALUE(x));
static_assert(IS_LVALUE(x+=y));
static_assert(IS_LVALUE("Hello world!"));
static_assert(IS_LVALUE(++x));

static_assert(IS_PRVALUE(1));
static_assert(IS_PRVALUE(x++));
static_assert(IS_PRVALUE(static_cast<double>(x)));
static_assert(IS_PRVALUE(std::string{}));
static_assert(IS_PRVALUE(throw std::exception()));
static_assert(IS_PRVALUE(doesNothing()));

static_assert(IS_XVALUE(std::move(s)));
// The next one doesn't work in gcc 8.2 but in gcc 9.1. Clang 7.0.0 and msvc 19.16 are doing fine.
static_assert(IS_XVALUE(S().x)); 

プライマリカテゴリを理解すると、混合カテゴリは退屈なものになります。

その他の例(および実験)については、コンパイラエクスプローラーの次のリンクを確認してください。ただし、アセンブリをわざわざ読んではいけません。すべての一般的なコンパイラで確実に機能するように、多くのコンパイラを追加しました。

14
Mohan 2016-07-25 18:26.

Stroustrupを読んで、右辺値と左辺値の区別を理解したと思った後でも混乱した点について、上記の優れた回答に対する1つの補遺。あなたが見るとき

int&& a = 3

int&&型として読み、それaが右辺値であると結論付けるのは非常に魅力的です。そうではありません:

int&& a = 3;
int&& c = a; //error: cannot bind 'int' lvalue to 'int&&'
int& b = a; //compiles

a名前があり、事実上左辺値です。&&のタイプの一部として考えないでくださいa。これaは、何にバインドできるかを示すものにすぎません。

これT&&は、コンストラクターの型引数にとって特に重要です。あなたが書くなら

Foo::Foo(T&& _t) : t{_t} {}

にコピー_ttます。あなたが必要

Foo::Foo(T&& _t) : t{std::move(_t)} {}引っ越したいなら。私が省略したときに私のコンパイラが私に警告したでしょうかmove

Related questions

MORE COOL STUFF

「水曜日」シーズン1の中心には大きなミステリーがあります

「水曜日」シーズン1の中心には大きなミステリーがあります

Netflixの「水曜日」は、典型的な10代のドラマ以上のものであり、実際、シーズン1にはその中心に大きなミステリーがあります.

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ケイト・ミドルトンは、州の夕食会と州の訪問中にカミラ・パーカー・ボウルズからスポットライトを奪いたくなかった、と専門家は言う.

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンが、オリビア・ワイルドが彼女とハリー・スタイルズとの間の「難しい」が「非常に友好的」な分割を恒久的にすることを望んでいる理由を見つけてください.

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする 

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする&nbsp;

エリザベス女王の死後、ケイト・ミドルトンが舞台裏で「非常に困難な時期」を過ごしていたと伝えられている理由を調べてください.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

フィリップス40インチ4Kカーブモニターレビュー:ゴーストをあきらめる

フィリップス40インチ4Kカーブモニターレビュー:ゴーストをあきらめる

フィリップスのBDM4037UWは、最大4つのフルHD入力を同時に表示できる40インチのウルトラHD曲面LCDモニターであり、マルチプラットフォームゲーマーに最適な大型モニターのようです。そして、それは、2、3の小さな失敗と1つの大きなつまずきがなければ、そうなるでしょう。

アトランタは2018年まで戻ってきませんが、ドナルドグローバーはFX用のテレビをもっと作っています

アトランタは2018年まで戻ってきませんが、ドナルドグローバーはFX用のテレビをもっと作っています

(写真:Rodin Eckenroth / Getty Images)良いニュースと悪いニュースがあります。前者?FXは本日、ドナルドグローバーがFXプロダクションと独占的な全体的な制作契約を結んだことを発表しました。つまり、グローバーからのより多くの番組がFXや他の場所で行われることを意味します。

スクリームクイーンズは、いくつかの「ゴーストストーリー」で地獄のようにメタを取得します

スクリームクイーンズは、いくつかの「ゴーストストーリー」で地獄のようにメタを取得します

ライアン・マーフィーのように、毎ターンショーランナーのIDについて多くを学ぶことはめったにありません。その奇妙なことは、特定の瞬間にライアンマーフィーの工芸品について言えることのすべてですが、彼がグリーの特徴を使ってスピンザボトルをプレイしている場合でも、アメリカンホラーストーリーの壁で衝撃画像のスパゲッティを投げている場合でも、それは光ります。

イーロンマスクは、Twitterのフィードバックに基づいてテスラの車に基本的な機能を追加し続けています

イーロンマスクは、Twitterのフィードバックに基づいてテスラの車に基本的な機能を追加し続けています

自動車のパイオニアでありテスラのCEOであるイーロンマスクは、ツイッターでのテスラの所有者のフィードバックに応えて、今週末に多くの時間を費やしました。フィードバックは建設的であり、すぐにより良い車になる可能性がありますが、フォーラムでは急速に成長している自動車メーカーのカスタマーサービスの問題に焦点を当てています。

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、子供向けのパズルの本の序文を書き、ジョージ王子、シャーロット王女、ルイ王子と一緒にテキストを読むと述べた.

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

Yak's Produce は、数十個のつぶれたメロンを野生動物のリハビリ専門家であるレスリー グリーンと彼女のルイジアナ州の救助施設で暮らす 42 匹の動物に寄付しました。

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

8 枚目のスタジオ アルバムのリリースに向けて準備を進めているデミ ロヴァートは、「スーパー グレート ガイ」と付き合っている、と情報筋は PEOPLE に確認しています。

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

イーサン プラスの誕生日のお祝いは、TLC のウェルカム トゥ プラスビルのシーズン 4 のフィナーレで、戦争中の母親のキム プラスと妻のオリビア プラスを結びつけました。

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

ホームオフィスのセットアップ術を極めよう!AppExert の開発者は、家族全員が一緒にいる場合でも、在宅勤務の技術を習得しています。祖父や曽祖父が共同家族で暮らしていた頃の記憶がよみがえりました。

2022 年、私たちのデジタル ライフはどこで終わり、「リアル ライフ」はどこから始まるのでしょうか?

20 年前のタイムトラベラーでさえ、日常生活におけるデジタルおよびインターネットベースのサービスの重要性に驚くことでしょう。MySpace、eBay、Napster などのプラットフォームは、高速化に焦点を合わせた世界がどのようなものになるかを示してくれました。

ニューロマーケティングの秘密科学

ニューロマーケティングの秘密科学

マーケティング担当者が人間の欲望を操作するために使用する、最先端の (気味が悪いと言う人もいます) メソッドを探ります。カートをいっぱいにして 3 桁の領収書を持って店を出る前に、ほんの数点の商品を買いに行ったことはありませんか? あなたは一人じゃない。

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

私たちが住んでいる世界を確実に理解するには、データが必要です。ただし、空間参照がない場合、このデータは地理的コンテキストがないと役に立たなくなる可能性があります。

Language