2026/07/04 T& と T&& の 違い
"&&"は後置詞の一つと考えると前回は述べたが、ならばその性格を明らかにしよう。
int val =...;
int& val =...;
int&& val =...;
の3つを比較しよう。
色々コンパイルエラーが出るかどうか試してみたところ
int val =...;なんでもOK
int& val =...;定数NG、加減剰余NG、変数は a->b.c[i] までOK
別名を付け一心同体になると考えると納得できる。
int がクラスになる時も試したが val はコンストラクターもデストラクターも動かない。
int&& val =...;定数OK、1変数NG、式OK
要するに「int& val」でNGなものが全部OKという事になる。
今ここでわかってしまったことがある
int& val = 左辺値、int&& val = 右辺値
という事だ。
世の中には 左辺値でも右辺値でもない式があるらしいが無視しよう。
一応サンプルプログラムを示す。
//
// T& の例
struct struct0{ int i; char c[10];};
struct struct1{ struct0 str0; int j;} str1;
struct1* pstr1 = &str1;
char& cc = pstr1->str0.c[3];//cc は pstr1->str0.c[3] の別名、pstr1->str0.c[3] が未定義でも可
cc = 'g';
Debug(cc, pstr1->str0.c[3]);//'g', 'g' と出力
pstr1->str0.c[3] = 'k';
Debug(cc, pstr1->str0.c[3]);//'k', 'k' と出力
//結論「int& x = y;」は y の別名を x とし一心同体になる
//
// T&& の例
int x = 70;
int&& b = x + 20;
Debug(b, x);//90, 70 と出力
x = 60;
Debug(b, x, b + x);//90, 60, 150 と出力
b = 10;//int&& 宣言した変数も int と同じように普通に使える
Debug(b, x);//10, 60 と出力
//結論 x と b の間に関係はない
|
以前デストラクターは';'と'}'の所で暗黙的に働くと述べたが、
結論として
int val = x + 20;//x + 20 を計算しそれを val にコピーし、計算結果は';'の所でデストラクトする
int& val = a->b.c[i];//変数 a->b.c[i] の別名として val を定義し一心同体となる。
val はコンストラクターもデストラクターも動かない
int&& val = x + 20;//x + 20 を計算しそれを val とし、';'の所では計算結果をデストラクトしない
int をクラス T にして試してみると
T& は上記と同じで別名になり、コンストラクターもデストラクターも動かない。
T val = 左辺値 の場合、コピーコンストラクターが動く。
T val = 右辺値 の場合、
ムーブコンストラクターがないとコピーコンストラクターが動く、
ムーブコンストラクターがあるとムーブコンストラクターが動く。
T&& val = 左辺値 の場合、コンパイルエラー
T&& val = 右辺値 の場合、
ムーブコンストラクターがないとコピーコンストラクターが動く、
ムーブコンストラクターがあるとムーブコンストラクターが動く。
ということになった。
クラスであれば、チャックライトを入れて色々試せるが
int のがどうなっているかは試せません。
ちょっと想像も含めています。
しかしムーブコンストラクターがあったとしても
sizeof(int) = 4、sizeof(int*) = 4
なので処理を早くする効果はそんなにないかも。