名前空間
変種
操作

値カテゴリ

提供: cppreference.com
< cpp‎ | language
 
 
C++言語
一般的なトピック
フロー制御
条件付き実行文
繰り返し文 (ループ)
ジャンプ文
関数
関数宣言
ラムダ関数宣言
inline 指定子
例外指定 (非推奨)
noexcept 指定子 (C++11)
例外
名前空間
指定子
decltype (C++11)
auto (C++11)
alignas (C++11)
記憶域期間指定子
初期化
値カテゴリ
評価順序
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点
文字 - 文字列 - nullptr (C++11)
ユーザ定義 (C++11)
ユーティリティ
属性 (C++11)
typedef 宣言
型エイリアス宣言 (C++11)
キャスト
暗黙の変換 - 明示的な変換
static_cast - dynamic_cast
const_cast - reinterpret_cast
メモリ確保
クラス
クラス固有の関数特性
特別なメンバ関数
テンプレート
その他
 
一般
値のカテゴリ (lvalue, rvalue, xvalue)
評価順序 (副作用完了点)
定数式
未評価式
一次式
ラムダ式(C++11)
リテラル
整数リテラル
浮動小数点リテラル
ブーリアンリテラル
文字リテラル および エスケープシーケンス
文字列リテラル
ヌルポインタリテラル(C++11)
ユーザ定義リテラル(C++11)
演算子
代入演算子: a=b, a+=b, a-=b, a*=b, a/=b, a%=b, a&=b, a|=b, a^=b, a<<=b, a>>=b
インクリメントとデクリメント: ++a, --a, a++, a--
算術演算子: +a, -a, a+b, a-b, a*b, a/b, a%b, ~a, a&b, a|b, a^b, a<<b, a>>b
論理演算子: a||b, a&&b, !a
比較演算子: a==b, a!=b, a<b, a>b, a<=b, a>=b, a<=>b(C++20)
メンバアクセス演算子: a[b], *a, &a, a->b, a.b, a->*b, a.*b
その他の演算子: a(...), a,b, a?b:c
デフォルト比較(C++20)
演算子の代替表現
優先順位と結合性
畳み込み式(C++17)
new 式
delete 式
throw 式
alignof
sizeof
sizeof...(C++11)
typeid
noexcept(C++11)
演算子オーバーロード
変換
暗黙の変換
const_cast
static_cast
reinterpret_cast
dynamic_cast
明示的な変換 (T)a, T(a)
ユーザ定義の変換
 

C++ の (演算子とその被演算子、リテラル、変数名など) は、それぞれ2つの独立した性質、および値カテゴリによって特徴付けられます。 それぞれの式は何らかの非参照型を持ち、それぞれの式は以下のように定義される3つの一次値カテゴリ prvaluexvaluelvalue のいずれかひとつだけに属します。

  • glvalue (“generalized” lvalue) は、その評価がオブジェクト、ビットフィールド、または関数の識別性を決定する式です。
  • prvalue (“pure” rvalue) は、その評価が以下のいずれかである式です。
  • 演算子の被演算子の値を計算する (そのような prvalue は結果のオブジェクトを持ちません)、または
  • オブジェクトまたはビットフィールドを初期化する (そのような prvalue は結果のオブジェクトを持つと言います)。 すべてのクラスおよび配列の prvalue は、たとえ破棄されるとしても、結果のオブジェクトを持ちます。 特定の文脈においては、結果のオブジェクトとしての一時オブジェクトを作成するために一時的な具体化が発生します。
  • xvalue (“eXpiring” value) は、そのリソースが再利用できるオブジェクトまたはビットフィールドを表す glvalue です。
  • lvalue (いわゆる左辺値。 歴史的には lvalue は代入式の左辺に現れるものを言いました) は、 xvalue ではない glvalue です。
  • rvalue (いわゆる右辺値。 歴史的には rvalue は代入式の右辺に現れるものを言いました) は、 prvalue または xvalue です。

ノート: この分類は過去の C++ のリビジョンで大幅な変更を経ました。 詳細は後述の歴史を参照してください。

目次

[編集] 一次カテゴリ

[編集] lvalue

以下の式は lvalue の式です。

  • 変数、関数テンプレート引数オブジェクト (C++20およびそれ以降)、データメンバの名前 (型にかかわらず)。 std::cinstd::endl など。 たとえ変数の型が右辺値参照であっても、その名前から構成される式は lvalue 式です。
  • 戻り値の型が左辺値参照である関数呼び出し式またはオーバーロードされた演算子式。 std::getline(std::cin, str)std::cout << 1str1 = str2++it など。
  • a = ba += ba %= b および他のすべての組み込みの代入および複合代入式。
  • ++a および --a — 組み込みの前置インクリメントおよび後置インクリメント式。
  • *p — 組み込みの間接参照式。
  • a[n] および p[n] — 組み込みの添字、ただし a[n] のいずれかの被演算子が配列の lvalue の場合 (C++11およびそれ以降)
  • a.mオブジェクトのメンバ式。 ただし m がメンバ列挙子または非静的メンバ関数であるか、 a が rvalue であり m が非参照型の非静的データメンバである場合を除きます。
  • p->m — 組み込みのポインタのメンバ式。 ただし m はメンバ列挙子または非静的メンバ関数である場合を除きます。
  • a.*mp — 組み込みのオブジェクトのメンバへのポインタ式。 ただし a が lvalue であり、 mp がデータメンバへのポインタである場合。
  • p->*mp — 組み込みのポインタのメンバへのポインタ式。 ただし mp がデータメンバへのポインタの場合。
  • a, b — 組み込みのコンマ式。 ただし b が lvalue の場合。
  • a ? b : c — 何らかの b および c に対する 三項条件式 (両方が同じ型の lvalue のときなど、詳細は定義を参照してください)。
  • 文字列リテラル"Hello, world!" など。
  • 左辺値参照型へのキャスト式。 static_cast<int&>(x) など。
  • 戻り値の型が関数への右辺値参照である関数呼び出し式またはオーバーロードされた演算子式。
  • 関数への右辺値参照型へのキャスト式。 static_cast<void (&&)(int)>(x) など。
(C++11およびそれ以降)

性質:

  • glvalue と同じ (下記参照)。
  • lvalue のアドレスを取ることができます。 &++i[1] および &std::endl は有効な式です。
  • 変更可能な lvalue は組み込みの代入および複合代入演算子の左側の被演算子として使用することができます。
  • lvalue は左辺値参照を初期化するために使用することができます。 これはその式によって表されるオブジェクトに新しい名前を紐付けます。

[編集] prvalue

以下の式は prvalue 式です。

  • リテラル (文字列リテラル)。 42true または nullptr など。
  • 戻り値の型が非参照である関数呼び出し式またはオーバーロードされた演算子式。 str.substr(1, 2)str1 + str2it++ など。
  • a++ および a-- — 組み込みの後置インクリメントおよび後置デクリメント式。
  • a + ba % ba & ba << b および他のすべての組み込み算術式。
  • a && ba || b!a — 組み込みの論理式。
  • a < ba == ba >= b および他のすべての比較式。
  • &a — 組み込みのアドレス取得式。
  • a.mオブジェクトのメンバ式。 ただし m がメンバ列挙子または非静的メンバ関数[2]であるか、または a が rvalue であり m が非参照型の非静的データメンバ (C++11以前)である場合。
  • p->m — 組み込みのポインタのメンバ式。 ただし m がメンバ列挙子または非静的メンバ関数[2]である場合。
  • a.*mp — 組み込みのオブジェクトのメンバへのポインタ式。 ただし mp がメンバ関数へのポインタ[2]であるか、または a が rvalue であり mp がデータメンバへのポインタ (C++11以前)である場合。
  • p->*mp — 組み込みのポインタのメンバへのポインタ式。 ただし mp がメンバ関数へのポインタ[2]である場合。
  • a, b — 組み込みのコンマ。 ただし b が rvalue である場合。
  • a ? b : c — 何らかの b および c に対する 三項条件式 (詳細は定義を参照してください)。
  • 非参照型へのキャスト式。 static_cast<double>(x)std::string{}(int)42 など。
  • this ポインタ。
  • 列挙子
(C++11およびそれ以降)
(C++20およびそれ以降)

性質:

  • rvalue と同じ (下記参照)。
  • prvalue は多相になれません。 それが表すオブジェクトの動的な型は、常にその式の型です。
  • 非クラスかつ非配列な prvalue は cv 修飾できません (ノート: 関数呼び出しまたはキャスト式は非クラスの cv 修飾された型の prvalue を生成することがありますが、その cv 修飾子は直ちに剥ぎ取られます)。
  • prvalue は不完全型であることはできません (void 型の場合 (下記参照)、 または decltype 指定子 で使用されるときを除きます)。

[編集] xvalue

以下の式は xvalue 式です。

  • 戻り値の型がオブジェクトへの右辺値参照である関数呼び出し式またはオーバーロードされた演算子式。 std::move(x) など。
  • a[n] — 組み込みの添字式。 ただし一方の被演算子が配列の rvalue である場合。
  • a.mオブジェクトのメンバ式。 ただし a が rvalue であり、 m が非参照型の非静的データメンバである場合。
  • a.*mpオブジェクトのメンバへのポインタ式。 ただし a が rvalue であり、 mp がデータメンバへのポインタである場合。
  • a ? b : c — 何らかの b および c に対する 三項条件式 (詳細は定義を参照してください)。
  • オブジェクトへの右辺値参照型へのキャスト式。 static_cast<char&&>(x) など。
(C++17およびそれ以降)

性質:

  • rvalue と同じ (下記参照)。
  • glvalue と同じ (下記参照)。

特に、すべての rvalue と同様に xvalue は右辺値参照に束縛し、すべての glvalue と同様に xvalue は多相であってもよく、非クラスの xvalue は cv 修飾されることもあります。

[編集] 混合カテゴリ

[編集] glvalue

glvalue 式は lvalue または xvalue のいずれかです。

性質:

  • glvalue は、左辺値から右辺値、配列からポインタ、または関数からポインタへの暗黙の変換で、 prvalue に暗黙に変換されることがあります。
  • glvalue は多相であることがあります。 それが表すオブジェクトの動的な型が、その式の静的な型と一致するとは限りません。
  • glvalue は (その式が許す場合は) 不完全型であっても構いません。

[編集] rvalue

rvalue 式は prvalue または xvalue のいずれかです。

性質:

  • rvalue のアドレスを取ることはできません。 &int()&i++[3]&42 および &std::move(x) は無効です。
  • rvalue は組み込みの代入または複合代入演算子の左側の被演算子として使用することはできません。
  • rvalue は const 左辺値参照を初期化するために使用することができます。 この場合、その rvalue が表すオブジェクトの生存期間はその参照のスコープが終わるまで延長されます。
  • rvalue は右辺値参照を初期化するために使用することができます。 この場合、その rvalue が表すオブジェクトの生存期間はその参照のスコープが終わるまで延長されます。
  • 関数の実引数として使用されたとき、かつ、関数の一方が右辺値参照引数を取り、他方が const 左辺値参照を取る2つのオーバーロードが利用可能なとき、 rvalue は右辺値参照オーバーロードに束縛します (そのため、コピーとムーブ両方のコンストラクタが利用可能であれば、 rvalue 引数はムーブコンストラクタを呼び出します。 コピーとムーブの代入演算子でも同様です)。
(C++11およびそれ以降)

[編集] 特殊なカテゴリ

[編集] 保留中のメンバ関数呼び出し

a.mf および p->mf (ただし mf非静的メンバ関数)、および式 a.*pmf および p->*pmf (ただし pmfメンバ関数へのポインタ) は、 prvalue 式として分類されますが、関数呼び出し演算子の左側の引数 (例えば (p->*pmf)(args)) の場合を除き、参照を初期化するために、または関数の引数として、あるいはいかなる目的のためにも使用することはできません。

[編集] void 式

void を返す関数呼び出し式、 void へのキャスト式、および throw 式は、 prvalue 式として分類されますが、参照を初期化するために、または関数の引数として使用することはできません。 値を破棄する式の文脈で (例えば式文全体として、あるいはコンマ演算子の左側の引数として)、および void を返す関数の return 文で使用することができます。 さらに、 throw 式は条件演算子 ?: の2つめおよび3つめの被演算子として使用しても構いません。

void 式は結果のオブジェクトを持ちません。

(C++17およびそれ以降)

[編集] ビットフィールド

ビットフィールドを指定する式 (例えば a.m ただし a は型 struct A { int m: 3; } の左辺値) は、 lvalue 式です。 代入演算子の左側の被演算子として使用できますが、アドレスを取ることはできず、非 const 左辺値参照をそれに束縛することはできません。 const 左辺値参照はビットフィールドの lvalue から初期化できますが、そのビットフィールドの一時コピーが作成されます。 これは直接ビットフィールドには束縛しません。

[編集] 歴史

[編集] CPL

プログラミング言語 CPL は式に対して値カテゴリを導入した最初の言語でした。 「右辺モード」ではすべての CPL の式を評価できますが、「左辺モード」では特定の種類の式のみが意味を持ちます。 右辺モードで評価されるとき、式は値 (右辺値、または rvalue) の計算のためのルールであるとみなされます。 左辺モードで評価されるとき、式は実質的にはアドレス (左辺値、または lvalue) を指定します。 このとき「左」および「右」は「代入の左」および「代入の右」の略でした。

[編集] C

C プログラミング言語は同様の分類に従いましたが、代入の役割はもはや十分ではありませんでした。 C の式は「lvalue 式」とそれ以外 (関数およびオブジェクトでない値) に分類されます。 「lvalue」はオブジェクトを表す式「locator value」を意味しました[4]

[編集] C++98

2011年より前の C++ は C のモデルに従いましたが、 lvalue でない式を表す名前「rvalue」を復活させ、関数を lvalue に分類し、参照は lvalue に束縛できるけれども const 参照だけは rvalue にも束縛できるというルールを追加しました。 いくつかの lvalue でない C の式が C++ では lvalue 式になりました。

[編集] C++11

C++11 におけるムーブセマンティクスの導入に伴い、値カテゴリが2つの独立した式の性質を分類するために再定義されました[5]

  • 識別性を持つ — 式が別の式と同じエンティティを参照するかどうかを決定することができる (例えばそれらが表すオブジェクトや関数の (直接的または間接的に取得した) アドレスを比較することによって)。
  • ムーブすることができる — ムーブセマンティクスを実装するムーブコンストラクタムーブ代入演算子、または他の関数オーバーロードが、その式に束縛できる。

C++11 では、

  • 識別性を持ち、ムーブできない式は、lvalue 式と呼ばれます。
  • 識別性を持ち、ムーブできる式は、xvalue 式と呼ばれます。
  • 識別性を持たず、ムーブできる式は、prvalue (「pure rvalue」) 式と呼ばれます。
  • 識別性を持たず、ムーブできない式は、使用されません[6]

識別性を持つ式は「glvalue 式」と呼ばれます (glvalue は「generalized lvalue」の略です)。 lvalue と xvalue はどちらも glvalue 式です。

ムーブできる式は「rvalue 式」と呼ばれます。 prvalue と xvalue はどちらも rvalue 式です。

[編集] C++17

C++17 では、いくつかの状況においてコピー省略が必須となり、それによって prvalue 式を、それらによって初期化された一時オブジェクトから分離することが要求されました。 この結果が今日私たちが使用している型システムです。 C++11 のスキームと異なり、 prvalue はもはやムーブされないことに注意してください。

[編集] 注釈

  1. i が組み込み型であるか、前置インクリメント演算子が左辺値参照で返すようにオーバーロードされていると仮定しています。
  2. 2.0 2.1 2.2 2.3 これは特殊な rvalue カテゴリです。 保留中のメンバ関数呼び出しを参照してください。
  3. i が組み込み型であるか、後置インクリメント演算子が左辺値参照で返すためにオーバーロードされていないと仮定しています。
  4. "A difference of opinion within the C community centered around the meaning of lvalue, one group considering an lvalue to be any kind of object locator, another group holding that an lvalue is meaningful on the left side of an assigning operator. The C89 Committee adopted the definition of lvalue as an object locator." -- ANSI C Rationale, 6.3.2.1/10.
  5. "New" Value Terminology by Bjarne Stroustrup, 2010.
  6. const prvalue (クラス型に対してのみ認められます) および const xvalue は T&& オーバーロードに束縛しませんが、それらは const T&& オーバーロードには束縛します。 これらも標準によって「ムーブコンストラクタ」および「ムーブ代入演算子」に分類され、この分類の目的に対しては「ムーブできる」の定義を満たします。 しかし、そのようなオーバーロードは引数を変更できず、実際のところは使用されません。 それらがない場合、 const prvalue および const xvalue は const T& オーバーロードに束縛します。

[編集] 欠陥報告

以下の動作変更欠陥報告は以前に発行された C++ 標準に遡って適用されました。

DR 適用先 発行時の動作 正しい動作
CWG 616 C++11 member access and member access through pointer to member of an rvalue resulted in prvalue reclassified as xvalue
CWG 1213 C++11 subscripting an array rvalue resulted in lvalue reclassified as xvalue

[編集] 関連項目

値カテゴリC言語リファレンス