Help us understand the problem. What is going on with this article?

右辺値は型ではない

More than 5 years have passed since last update.

C++ の右辺値について混乱していたので、右辺値と右辺値参照についてメモしておく。

value category

C++ の式は、型とは別に value category というものを持つ。value category は prvalue, xvalue, lvalue のいずれかであり、prvalue と xvalue をまとめて 右辺値 と呼ぶ。(prvalue, xvalue, lvalue については後述)

注意すべき点として、

  • 同じ型を持つ式でも、異なる value category を持つことがある。
  • 同じオブジェクトを返す式でも、異なる value category を持つことがある。

例えば、

string s = string("hello ") + string("world");
strint t = s;

というコードにおいて、1行目の string("hello ") + string("world") の型と、2行目の右辺の s の型は同一(string 型)であるが、value category は異なっている (それぞれ prvalue と lvalue)。

ひどい例として、以下のような場合、

string&& r = string("hello");
string t = r;

r の型は string への右辺値参照だが、2行目の r という式の value category は lvalue になる。

左辺値の式から無理やり右辺値を作りたい場合は std::move 関数を使ってキャストする。

string s("hello");
string&& r = move(s);    // move(s) は xvalue (右辺値の一種)

関数のオーバーロードと右辺値

string hoge = "piyo";
string x = ???;

という式を考える。

??? の部分が hoge のような左辺値だった場合、string のコピーコンストラクタが呼び出される。一方、??? の部分が move(hoge) のような右辺値の式だった場合、string のムーブコンストラクタが呼び出される。

一般に、ある関数 f が「左辺値参照を取るバージョン」と「右辺値参照を取るバージョン」の2通りにオーバーロードされていて、かつ f の引数が右辺値の式になっている場合、右辺値参照を取るバージョンの f が呼び出される。コピーコンストラクタ vs ムーブコンストラクタの例は、このルールのスペシャルケースになっている。

prvalue, xvalue, lvalue について

prvalue

prvalue (pure rvalue) は一時オブジェクトを生じさせる式。

例:

  • 文字列以外のリテラル (100 とか nullptr とか)
  • 戻り値の型が参照型でない関数呼び出し式
  • 組み込みの算術式、論理式、比較式など

xvalue

xvalue (eXpiring value) は move 元のオブジェクトを表す式。

例:

  • 戻り値の型が右辺値参照である関数呼び出し
  • 右辺値参照へのキャスト式
  • xvalue である式の non-static クラスメンバへのアクセス式

lvalue

lvalue は一時的でないオブジェクトを表す式。

例:

  • 変数名
  • 戻り値の方が左辺値参照である関数呼び出し
  • 代入式
  • 文字列リテラル
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away