タイトルが結論だが,複合代入演算子では,現在の値を処理するのは最後というお話.
改めて書く必要はないが,落とし穴に落ちてしばらく悩んでしまったのでメモ.
初心者に説明する際に注意するかと言われるとそうはしないと思う.
よくある複合代入演算子の説明
auto i {4};
// same after calculation
i = i * (5 + 3) / 2; // (1)
i *= (5 + 3) / 2; // (2)
(1)式と(2)式は等価である.
うまくゆかない例
auto i1 {4}, i2 {4};
i1 = i1 * (2 + 3) / 2; // (1)'
i2 *= (2 + 3) / 2; // (2)'
(1)'式では,iが計算の始めに入っている.ここでは/2
によって割った際に割り切れている.
計算結果は10である.
(2)'式では,先にi以外の演算が行われる.ここでは/2
によって割った際に0方向に丸められる.
計算結果は8である.
原因と対策
原因は先程も述べたが,計算順が異なるために実は同一となっていない.
正しい等価な式は以下の通り.
auto i {0};
i = i * ((2 + 3) / 2);
i *= (2 + 3) / 2;
最後に演算される点に注意しよう.
もし,最初に変数を読む必要があれば複合代入演算子は用いれない点にも注意が必要だ.
必要なのに,複合代入演算子に変えようとしてはいけない.