More Effective C+----(7)「&&」、「|」、「,」をリロードしない


Item M 7:「&&」、「|」、「,」をリロードしない
振り替えは出典を明記してください
Cと同様、C++
ブール式短絡評価法(short-circuit evaluation)を使用します.これは
ブール式の真偽値が決定されると、一部の式がテストされていない場合でも、ブール式は演算を停止します.例:
char *p;
...
if ((p != 0) && (strlen(p) > 10)) ...

ここは心配しないで
pが空の場合、strlenは正しく動作しません.pが0に等しくないテストに失敗した場合、strlenは呼び出されません.同じ:
int rangeCheck(int index)
{
if ((index < lowerBound) || (index > upperBound)) ...
...
}

indexがlowerBoundより小さい場合、upperBoundとは比較されません.
以前から,上記の挙動特性はCとC++のプログラマーに繰り返し注入されていたので,彼らはこの特性を知っていた.短絡評価法に依存してプログラムを書く.例えば、上記の第1のコードでは、pが空のポインタである場合、strlenが呼び出されないことを確保することが重要である.C++標準説(C標準説)
空のポインタでstrlenを呼び出し、結果は不確定です.
C++は、ユーザー定義のタイプに応じて&&&||オペレータをカスタマイズできます.メソッドは、関数operator&&&とoperator||をリロードし、グローバルリロードまたはクラスごとにリロードできます.しかし、この方法を使用したい場合は、ゲームのルールを大きく変えていることを知っておく必要があります.短絡評価法の代わりに関数呼び出し法を使用しているからです.つまり、オペレータ&&をリロードすると、コードは次のようになります.
if (expression1 && expression2) ...

コンパイラの場合、次のいずれかのコードに等しくなります.
if (expression1.operator&&(expression2)) ...
                              // when operator&& is a
                              // member function
if (operator&&(expression1, expression2)) ...
                              // when operator&& is a
                              // global function

これは何の違いもないようですが、関数呼び出し法と短絡評価法は絶対に違います.
まず、関数が呼び出されると、そのすべてのパラメータを演算する必要があるので、関数functions operator&&とoperator|を呼び出すと、両方のパラメータが計算され、言い換えれば、
短絡計算法は採用されていない.
2つ目は,C++言語仕様では関数パラメータの計算順序が定義されていないため,式1と式2のどちらが先に計算されるかを知ることができない.左パラメータから右パラメータまでの計算順序を持つ短絡計算法とは完全に逆である可能性がある.
したがって、&&&または|を再ロードすると、プログラマーが望む動作特性や使用する動作特性を提供することはできませんので、&&&&と|を再ロードしないでください.
同じ理由が適用されます
カンマオペレータですが、深く研究する前に、あまり驚かないように一時停止します.「カンマオペレータ?カンマオペレータはどこにありますか?」確かに存在する.カンマオペレータは式を構成するために使用され、forループの更新部分(update part)でよく遭遇します.例えば、以下はKernighan's and Ritchie's古典書The C Programming Language第2版(Prentice-Hall,1988)の関数に由来する.
// reverse string s in place
void reverse(char s[])
{
for (int i = 0, j = strlen(s)-1;
     i < j;
     ++i, --j)         //  !      !
{
  int c = s[i];
  s[i] = s[j];
  s[j] = c;
}
}

forサイクルの最後の部分では,iが増加すると同時にjが減少する.ここでカンマを使うのは便利です.最後の部分では1つの式しか使えないので、式を分けてiとjの値を変えるのは合法ではありません.
組み込みタイプ&&&|,C++には、それらがどのように演算されるかを定義するルールがあります.
これと同様に、カンマオペレータの計算方法を定義するルールもあります.
カンマを含む式は、まずカンマの左側の式を計算し、次にカンマの右側の式を計算します.式全体の結果は、カンマの右側の式の値です.したがって、上記のループの最後の部分では、コンパイラはまず++iを計算し、次に-jであり、カンマ式の結果は-jである.
なぜこれらの内容を知る必要があると思いますか?この動作特性を真似する必要があるので、自分のカンマオペレータ関数を大胆に書きたい場合は.
残念なことに、あなたは真似できません.
非メンバー関数operatorを書くと、関数(operator)呼び出し時に2つの式がパラメータとして渡されるため、左の式が右の式より先に計算されることは保証されません.しかし、関数パラメータの計算順序を制御することはできません.だからメンバー関数以外の方法は絶対にだめです.
残りはメンバー関数operatorを書く可能性だけです.ここでもカンマの左側の式で先に計算される動作特性に頼ることはできません.
コンパイラは必ずしもこの方法で計算する必要はありません.コンマオペレータを再ロードして、予想通りの動作特性を保証することはできません.それを重荷するのは完全に軽率な行為だ.
この重荷の悪夢が終わったかどうか考えているかもしれません.結局、カンマオペレータをリロードできれば、リロードできないものはありますか?表示されているように、いくつかの制限があります.
次のオペレータは再ロードできません.
.              .*              ::             ?:
new          delete        sizeof      typeid
static_cast  dynamic_cast  const_cast  reinterpret_cast

リロードできます.
operator new        operator delete
operator   new[]    operator delete[]
+    -   *   /   %   ^     &   |     ~
!    =   <   >  +=   -=   *=   /=   %=
^=  &=  |=  <<  >>   >>=  <<=  ==   !=
<=  >=  &&  ||  ++   --    ,   ->*  ->
()  []

(newとdelete、operator new、operator delete、operator new[],and operator delete[]については、条項M 8を参照)
もちろん、これらのオペレータを再ロードできるのは、再ロードする理由ではありません.オペレータのリロードの目的は、あなたの知識で他の人を惑わすのではなく、プログラムを読みやすく、書きやすく、理解させることです.オペレータをリロードする良い理由がない場合は、リロードしないでください.
どんなに努力しても、彼らの行動特性を期待通りにすることはできないので、良い理由を見つけるのは難しい.
増加:
C++Primer第5版で明確に提出され、
アドレス演算子を再ロードするべきではありません.C++言語では、クラスタイプオブジェクトに使用する2つの演算子の特殊な意味が定義されているため、ほとんどの演算子とは異なります.この演算子にはすでに内蔵されている意味があり、リロード後は通常とは異なり、クラスのユーザーが使用できなくなります.