Cpp 右辺値参照 新しいページはコチラ

提供: yonewiki
移動: 案内, 検索
(右辺値参照)
(右辺値参照)
42行: 42行:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
VC++なら記述した段階で、不正な代入としてチェックされ、nSizeの文字の下に赤い波線が付きます。
 
VC++なら記述した段階で、不正な代入としてチェックされ、nSizeの文字の下に赤い波線が付きます。
 +
 +
 +
以下は[[C キャスト | キャスト]]による明示的な右辺値参照代入の指定です。
 
<syntaxhighlight lang="cpp">
 
<syntaxhighlight lang="cpp">
 
int = nSize
 
int = nSize
 
int&& rrefnSize = static_cast<int&&>(nSize); //これはOK。
 
int&& rrefnSize = static_cast<int&&>(nSize); //これはOK。
 
</syntaxhighlight>
 
</syntaxhighlight>
このようにint&&型に[[C キャスト | キャスト]]すれば大丈夫です。これはどういう事かというと、キャストがされると結局は参照が出来るようになるというだけなので、通常の参照と変わらないです。ただ型が右辺値参照で扱われる参照になるので、このあと再度、右辺値を代入することはできて、nSizeの中身が変更されます。ただし、右辺値で無い値を入れることは出来ないので、再度、キャスト付きでしか通常の参照のやり直しをすることはできません。
+
このように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(){
 
int Function(){
<nowiki> </nowiki> return 1;
+
  return 1;
 
}
 
}
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
  int&& rrefnCnt = Function();//これはOK。
 +
  return 0;
 +
}
 +
</syntaxhighlight>
 +
上記のように関数の返り値も右辺値として扱われますので、返り値の型が一致すれば右辺値参照型への代入ができます。構造体やクラスのメンバ関数に対してもキャストすることなく右辺値として参照を受け取ることができます。
  
のような関数があったとして、int&& rrefnCnt = Function();とすることもできます。構造体やクラスのメンバ関数に対してもキャストすることなく右辺値として参照を受け取ることができます。このような右辺値戻り値を引数にとるような関数で演算子のオーバロードによる代入演算子の再定義を活用すれば、とっておかなくてもいい引数であるがゆえに受け取った引数をコピーせず、移動させることで、代入するような関数を作ることができます。言葉での説明ではイメージできないと思うので、実際にやってみた方がいいですね。
+
このような右辺値戻り値を引数にとるような関数で演算子のオーバロードによる代入演算子の再定義を活用すれば、とっておかなくてもいい引数であるがゆえに受け取った引数をコピーせず、移動させることで、代入するような関数を作ることができます。言葉での説明ではイメージできないと思うので、実際にやってみた方がいいですね。
  
  
 
通常はとっておかなくていいものを残すとは、どういうことなのかを示す具体的なサンプルは作成中です。右辺値が必要になるようなプログラムって難しいですから、ちょっと時間下さい。っていつまでw
 
通常はとっておかなくていいものを残すとは、どういうことなのかを示す具体的なサンプルは作成中です。右辺値が必要になるようなプログラムって難しいですから、ちょっと時間下さい。っていつまでw

2014年10月23日 (木) 00:00時点における版



個人用ツール
名前空間

変種
操作
案内
ツールボックス