Cpp 右辺値参照のソースを表示
新しいページはコチラ
移動:
案内
,
検索
<table class="mbox-small" style="border:1px solid #aaa; background-color:#f9f9f9; width:22em;" id="RealTitleBanner"> <tr> <td style="width:1px;"></td> <td class="mbox-text plainlist" style="">本来の表記は「<b><span id="RealTitle" style="font-size:large;">C++ 右辺値参照</span></b>」です。この記事に付けられた題名は{{記事名の制約}}から不正確なものとなっています。</td> </tr> </table> ※このページでは[[C PlusPlus|C++]]にのみ存在する機能として、記事タイトルが<nowiki>C++ 右辺値参照</nowiki>になっています。<br /> <br /> == '''右辺値参照''' == [[Cpp 参照]]の特殊なパターンとして右辺値参照があります。あまり知られていないという点で特殊と記述しましたが、知っているひとからすれば、ごく自然なC++の言語仕様の一部に過ぎないです。 右辺値というとa = b;のように書くとbが方程式の右辺値です。このようなものの参照?って言われてもピンとこないかもしれませんが、よく右辺値にくるものの参照という意味で、オブジェクトをもたいない値の参照というような技術になります。オブジェクトをもたない値というのは具体的には、以下のようなものの右辺にくるものです。 <syntaxhighlight lang="cpp"> int a = 256; int a = function(); </syntaxhighlight> 通常はメモリのどこかにおかれるものですが、意識したことの無いようなものです。 こういうものを参照するための型として変数の型名の後ろに&&記号をつけて宣言する型を右辺値参照と呼びます。具体的には以下のように使うことができます。 <syntaxhighlight lang="cpp"> int&& rrefnSize = 256; printf("rrfnSize Addres->%x, rrefnSize Value->%d\n",&rrefnSize,rrefnsize); </syntaxhighlight> 出力結果 <syntaxhighlight lang="text"> rrfnSize Addres->46f85c, rrefnSize Value->256 </syntaxhighlight> だから、何?普通のint型と何も変わらないような感じですよね。でもこの参照は右辺値を参照するためのものなので、通常の変数を渡すとコンパイルエラーになります。これははっきりと通常ポインタ変数で扱わないものを型として区別できるとことが、この右辺値参照の活用の道となっています。右辺値というは通常は変数にはとっておかなくていい、一時的な値です。その通常はとっておかなくていいような値を右辺値参照によって取り出して引数として受け取り、それを活用しようとする技術です。 <syntaxhighlight lang="cpp"> int = nSize int&& rrefnSize = nSize; //これは駄目。 </syntaxhighlight> このようにすると以下のようなコンパイルエラーとなります。 <syntaxhighlight lang="text"> error C2440: '初期化中' : 'int' から 'int &&' に変換できません。 </syntaxhighlight> VC++なら記述した段階で、不正な代入としてチェックされ、nSizeの文字の下に赤い波線が付きます。 以下は[[C キャスト | キャスト]]による明示的な右辺値参照代入の指定です。 <syntaxhighlight lang="cpp"> int = nSize int&& rrefnSize = static_cast<int&&>(nSize); //これはOK。 </syntaxhighlight> このようにint&&型に[[C キャスト | キャスト]]すれば大丈夫です。これはどういう事かというと、キャストがされると結局は参照が出来るようになるというだけなので、通常の参照と変わらないです。ただ型が右辺値参照で扱われる参照になるので、このあと再度、右辺値を代入することはできて、nSizeの中身が変更されます。ただし、右辺値で無い値を入れることは出来ないので、再度、キャスト付きでしか通常の参照のやり直しをすることはできません。このようなキャストは以下のようなstd::move()というC++標準関数を指定することでも同様の動作を実現できます。 <syntaxhighlight lang="cpp"> int = nSize int&& rrefnSize = std::move(nSize); //キャストと同じで、OK。 </syntaxhighlight> std::moveは右辺値でない変数も右辺値としてキャストする関数です。型名を書かなくても良いので、記述しやすいというのがこの関数の利点です。右辺値参照型というのは、右辺値のような一時的にメモリに配置されるものの、それ自体は消えてしまって、次に使うことはないような値ですので、このような代入をしたということは、もうその変数での利用はしないということを宣言したようなものですから、元の値は残さなくていいという意味でmoveという名前が付いています。実際にはmove関数で代入した後も元の変数での操作が出来るので、早いところ手動で消滅させたいものですが、動的に生成しなかった変数はプログラム内で宣言した領域内の終了まで残っているので、右辺値とは再利用できないものを扱うものなので再利用しないようにした方がよいでしょう。動的に生成したものを右辺値参照でキャストした場合も元のポインタ変数にヌルを設定するようにします。場合によっては、右辺値参照によって取得した変数を利用したクラスが消滅する際に、元の値も同時に消滅して、次に元の値を保持していたクラスが消滅する際に動作するデストラクタが、元の値のポインタの実体を消滅させる処理をするときに、すでに消滅済で、エラーになる場合があります。元の値のポインタ変数を消滅させる前に右辺値参照として活用するための手順を踏まないとキャストした意味がなくなってしまいますので手順が大事になります。ここでは、右辺値にキャストした値は右辺値として振る舞うために使われるべきなのだということを理解してもらえれば良いと思います。こうした右辺値参照へのキャストの活用方法についてはもう少しあとで触れます。 以下はキャストを必要としない右辺値参照のパターンです。 <syntaxhighlight lang="cpp"> int Function(){ return 1; } int _tmain(int argc, _TCHAR* argv[]) { int&& rrefnCnt = Function();//これはOK。 return 0; } </syntaxhighlight> 上記のように関数の返り値も右辺値として扱われますので、返り値の型が一致すれば右辺値参照型への代入ができます。構造体やクラスのメンバ関数に対してもキャストすることなく右辺値として参照を受け取ることができます。 このような右辺値戻り値を引数にとるような関数で演算子のオーバロードによる代入演算子の再定義を活用すれば、とっておかなくてもいい引数であるがゆえに受け取った引数をコピーせず、移動させることで、代入するような関数を作ることができます。言葉での説明ではイメージできないと思うので、実際にやってみた方がいいですね。 通常はとっておかなくていいものを残すとは、どういうことなのかを示す具体的なサンプルは作成中です。右辺値が必要になるようなプログラムって難しいですから、ちょっと時間下さい。っていつまでw
テンプレート:記事名の制約
(
ソースを閲覧
)
Cpp 右辺値参照
に戻る。
個人用ツール
18.116.51.133
このIPアドレスのトーク
ログイン
名前空間
ページ
議論
変種
表示
閲覧
ソースを表示
履歴表示
操作
検索
案内
メインページ
コミュニティ・ポータル
最近の出来事
最近の更新
おまかせ表示
ヘルプ
ツールボックス
リンク元
関連ページの更新状況
特別ページ