LoginSignup
22
12

More than 5 years have passed since last update.

僕「参照の && ってなに?」

Last updated at Posted at 2019-04-21

僕「&&ってなに?」

僕「C++のコード、&&みたいな記号をたまに見かけるけど、これは何なんだろう・・・」
女の子「ああ、それは右辺値参照(、ユニバーサル参照)を宣言するときの記号だよ~」
僕「右辺値参照?」
女の子「&を使って参照を宣言できることは知ってるじゃん?」
僕「うん」
女の子「それは、左辺値参照なの」
女の子「同じように、&&を使って宣言された参照型が右辺値参照なのだ」

int a;
int & b = a;  // 左辺値参照
int && c = 0; // 右辺値参照

女の子「そして、左辺値左辺値参照を初期化、右辺値右辺値参照を初期化することができて」
女の子「これらは一般に参照と呼ばれるの」
女の子「これだけの違いで、実際にこれらの参照を使うときの意味は同じ
僕「なるほど~ところで、左辺値右辺値ってなに?」
女の子「それはの種類」
僕「なにがちがうの?」
女の子「うーん、簡単にはいえないな~」

値カテゴリ

(僕「ちょっと気になったんだけど、式って言った?値じゃなくて?」)
(女の子「厳密にいえばそう。 左辺値、右辺値は、その名前に反して式の分類なのだよ」)

女の子「たとえば、下の図は式の分類である値カテゴリの全体図(N3337 3.10 図1のコピペ)」

Expression category taxonomy

女の子「式はglvaluervalueに分類することができて、それらはさらにlvaluexvalueprvalueに分類することができるん」
女の子「詳しくは値カテゴリ - cppreference.comに書いてあるので、簡単な説明だけするね」
女の子「すごく簡単に言えば、」

  • lvalue(左辺値) : 式にアドレスをとれるもの。代表的なのは、変数、関数の名前
  • xvalue : 一時オブジェクト、std::move(x)など
  • prvalue : アドレスが取れないもの。代表的には、戻り値の型が参照でない関数呼び出し式など
  • rvalue(右辺値) : prvalue または xvalue のいずれか
  • glvalue : lvalue または xvalue

女の子「だよ」

僕「ううん・・・オブジェクトの名前とかなら左辺値、関数呼び出しみたいなのなら右辺値でおk?」
女の子「だいたいおk」

ユニバーサル参照(forwarding reference)

~数日後~
僕「なんだか謎味深いコード見つけたんだけど・・・」
女の子「どしたん」
僕「これみて・・・」

#include <iostream>
#include <string>

template<typename T>
void print(T&& arg) // <--
{
    std::cout << std::forward<decltype(arg)>(arg) << '\n';
}

int main()
{
    std::string str = "nyan";
    print(str);
}

僕「この&&、どう見ても右辺値参照なんだけど、普通に動くんだよこのコード・・・」
女の子「あー、このT&&ユニバーサル参照(forwarding reference)って呼ばれているものだね~」
女の子「templateとか、auto&&がくっついてるのは、とりあえずなんでも受け取れるのだよ」
僕「まじか・・・」
女の子「そう」

僕「でも、なんで?」
女の子「この挙動の本質っぽいものは、参照の圧縮って呼ばれているものなの」
女の子「この場合、Tstd::string &に推論されるけど、このTって&&くっついてるじゃん?」
僕「うん」
女の子「でも参照の参照って作れないじゃん?」
僕「うん」
女の子「だから、コンパイラさんが気を利かせて、いい感じに推論してくれるんだよ~」
女の子「そんな感じで、Tstd::string &に推論されて、」
女の子「T&&もいい感じにstd::string &になるのだよ」
僕「はえ~」

(女の子「ちなみに、T&&で受け取って、std::forwardでほかの関数の引数にそのまま渡すのは、」)
(女の子「完全転送って呼ばれるてるよ~」)

ちょっと注意

  1. ユニバーサル参照(forwarding reference)はなんでも受け取れてしまうので、オーバーロードがこれに解決しがちだよ
  2. (完全転送のstd::forwardは、std::moveと同じように同じものに対して何回もやっちゃダメだよ!)

参考リンク

ムーブセマンティクスについて -> 本当は怖くないムーブセマンティクス - yohhoyの日記(別館)
完全転送について-> C++のムーブと完全転送を知る - Fixstars Tech Blog /proc/cpuinfo
値カテゴリについて -> 値カテゴリ - cppreference.com
いろいろ -> 右辺値参照・ムーブセマンティクス - cpprefjp C++日本語リファレンス

22
12
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
12