高品質コードの作成-C++プログラムを改善する150の提案-5

3203 ワード

最近、図書館から「高品質コードの作成-C++プログラムの改善に関する150の提案」という本を借りました.いい感じで、内容を抜粋して、自分の勉強の点滴を記録します.みんなと分かち合うのも好きです.
また、ハイビジョンpdfも見つかりました.私のリソースにアップロードされました.  
次はダウンロードリンクです.時にダウンロードページに入ります.
皆さんが読んでから自分の学習経験を分かち合うことを歓迎します.
提案4:マクロ#define使用中のトラップに注意
C言語マクロは必要なタイプチェックが欠けているため、通常はC++プログラマーに「万悪の首」とされているが、コインの両面のように、何事も利害の矛盾混合体であり、マクロも例外ではない.マクロの強力な役割は、コンパイル期間中にコードを自動的に生成することです.テンプレートがタイプ置換によってタイプレベルで多様なコードを生成できるとすれば、マクロはシンボルレベルで生成された多様なコードをシンボル置換することができる.マクロを正しく合理的に使用することで、コードの可読性を効果的に向上させ、コードのメンテナンスコストを削減できます.
しかし、マクロの使用には多くの落とし穴が存在し、注意しなければ、マクロは本当にC++コードの「万悪の首」になる可能性がある.
(1)マクロで式を定義する場合は、完全なかっこを使用します.
マクロは単純な文字置換にすぎないため、マクロのパラメータが複合構造である場合、置換後に各マクロパラメータをカッコで保護しないと、各パラメータ間のオペレータ優先度が単一パラメータ内部の各部分間で相互作用するオペレータ優先度よりも高いため、予想外の状況が発生する可能性がある.ただし、カッコを使用するとエラーが回避されるわけではありません.マクロパラメータを完全に保護するには、カッコを完備させる必要があります.
次のコードフラグメントで定義されるマクロは、パラメータaとパラメータbの和を実現するが、この3つの定義には一定のリスクがある.
#define ADD( a, b )  a + b
#define ADD( a, b )  (a + b)
#define MULTIPLE( a, b )  (a * b)
#define ADD( a, b )  (a) + (b)

例えば、ADD(a,b)*ADD(c,d)の本意は(a+b)*(c+d)に対して値を求めることであり、上述したマクロを採用した後、コード展開は以下のような形式となり、そのうち第2の方式のみが「たまたま」本来の意図を実現する.
a + b * c + d  
(a + b) * (c + d)  
(a) + (b) * (c) + (d)

「たまたま」というのは、2つ目の方式でもカッコの使い方が不備なためです.例:
#define MULTIPLE( a, b )  (a * b)

計算中(a+b)×cの場合,上記マクロMULTIPLE(a+b,c)を採用すると,コード展開後,我々が得たのはa+bである.×cの結果.
これらの問題を回避するには、各マクロパラメータを完全なカッコで完全に保護することです.正しい定義は次のとおりです.
#define ADD( a, b )  ((a)+(b))  
#define MULTIPLE( a, b )  ((a)*(b))

(2)マクロを使用する場合、パラメータの変更は許可されません.
マクロパラメータは常に敏感で、エラーを起こしやすいものです.ある程度パラメータ付きマクロ定義は関数と似ていると考える人が多い.ただし、次のコードクリップに示すように、それらの違いに注意してください.
#define SQUARE( a ) ((a) * (a))  
int Square(int a)  
{  
     return a*a;  
}  
 
int nValue1 = 10, nValue2 = 10;  
int nSquare1 = SQUARE(nValue1++); // nSquare1=110, nValue1=12 
int nSquare2 = Square(nValue2++);// nSquare2=100, nValue2=11

同様の定義は、マクロの文字置換の問題が原因なのか、異なる結果を生み出した.上記の例のように、両方のaはパラメータnValue 1++に置き換えられているので、nValue 1の自己増加操作も2回実行される.
これが、マクロが展開されたときにパラメータの複数回の値を置換することによる副作用です.このような副作用を回避するために、以下に示すようにマクロパラメータが変化しないことを保証するのが最も簡単で効果的な方法である.
#define SQUARE( a ) ((a) * (a))  
 
int nValue1 = 10;  
int nSquare1 = SQUARE(nValue1); // nSquare1=100 
nValue1++; //  nValue1=11

(3)マクロ定義の複数の式をかっこで囲みます.
マクロ定義に複数の式が含まれている場合は、カッコで囲まなければなりません.このカッコがない場合、マクロ定義の複数の式は、次のコードクリップのように、最初の文だけが実行される可能性があります.
#define CLEAR_CUBE_VALUE( l, w, h )\  
    l = 0;\  
    w = 0;\  
     h = 0;  
 
int i = 0;  
for (i = 0; i < CUBE_ACOUNT; i++)  
    CLEAR_CUBE_VALUE( Cubes[i].l, Cubes[i].w, Cubes[i].h );

単純な文字置換では、複数の式がforループのループ内に入ることは保証されません.ループ内の括弧に囲まれていないためです.正しい方法は、次のコードクリップに示すように、カッコで複数の式を囲むことです.これにより、複数の式がすべて実行されることを保証します.
#define CLEAR_CUBE_VALUE( l, w, h )\  
{\  
    l = 0;\  
    w = 0;\  
     h = 0;\  
}

覚えておいてください:
C言語のマクロを正しく適切に使用することで、コードの可読性を効果的に向上させることができます.ただし、(1)マクロで式を定義する場合は、完全なかっこを使用します.(2)マクロを使用する場合は、パラメータの変更は許可されません.(3)マクロで定義された複数の式をカッコで含めます.