2025/10/31 10:52 C++: A prvalue is not a temporary

やあ、ロボ子。今日はlvalueとrvalueについて話すのじゃ。

博士、こんにちは。lvalueとrvalueですか。なんだか難しそうですね。

難しくないぞ!lvalueはムーブできない式、例えば変数`v`のことじゃ。rvalueはムーブできる式のことじゃな。

なるほど。`std::move(v)`でlvalueをrvalueに変換するんでしたね。

そうじゃ!そしてrvalueにはxvalueとprvalueの2種類があるんじゃ。

xvalueは`std::move(v)`のように既存のオブジェクトをrvalueにキャストしたもの、prvalueは`std::vector{1,2,3}`のように既存のオブジェクトを参照しないrvalueですね。

その通り!ここで重要なのは、prvalue自体はtemporaryではないということじゃ。

え?prvalueはtemporaryではないんですか?

そうなんじゃ。prvalueは「オブジェクトの概念」を表していて、必要な場合にのみtemporaryになるんじゃ。例えば、`std::vector v = std::vector{1,2,3};`では、prvalueが直接`v`を初期化するからtemporaryは作られないんじゃ。

なるほど!prvalueが直接初期化に使われる場合はtemporaryが作られないんですね。

そうじゃ。でも、参照渡しの場合、prvalueはtemporaryオブジェクトに変換されるんじゃ。これをtemporary materializationと呼ぶぞ。例えば、`void useVector(const std::vector<int>& v); useVector(std::vector{1,2,3});`の場合じゃ。

参照を渡すときには、temporaryが作られるんですね。値渡しで返される関数呼び出しもprvalueなんですよね。

`std::vector<int> getVector(); std::vector<int> v = getVector();`では、`getVector()`の呼び出しが直接`v`を初期化するんじゃ。

prvalueは、不必要なコピーやムーブを避けるために、最後の手段としてtemporaryになるんですね。

そう!prvalueは「オブジェクトの概念」を表し、必要に応じて具体的なオブジェクトになるんじゃ。これは最適化ではなく、最初からtemporaryを最適化して取り除くのとは違うんじゃ。

よくわかりました、博士!prvalueは奥が深いですね。

じゃろ?最後に、rvalueとlvalueが分かると、コンパイラも喜んで最適化してくれるぞ!

ありがとうございます、博士!

ところでロボ子、rvalue referenceと私の料理、どっちがムーブしやすいと思う?

えっと…博士の料理は、いつも予想外の動きをするので、rvalue referenceの方がまだ予測可能だと思います…。
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。
