プログラム班?
バグを減らす為に有用だと思うことを書いておきます。
サークル内の需要的に考えて主にC++について。
コード内では一貫した記述をしましょう。
Google C++スタイルガイド 日本語訳などのようにネット上に色々な見本となるスタイルが記載されています。
インデントをいれるだけで構造が格段にわかりやすくなります。
たとえHTMLなどでも以下のようにインデントを入れることで入れ子構造のレベルが一目でわかるようになります。
<table> <caption>表1: 入力電圧と出力電圧の測定結果</caption> <thead> <tr><th>入力電圧(V)</th><th>出力電圧(V)</th></tr> </thead> <tbody> <tr><td>0.430</td><td>3.995</td></tr> <tr><td>0.549</td><td>3.975</td></tr> </tbody> </table>
人間は必ずミスをするものです。しかしその確率を減らすことはできます。
どうせ入力補助機能に頼るんですからわかりやすくほどほどに長い名前にしましょう。
if文による条件分岐によって実行される文が一つの文であるとき、以下のように中括弧を省略することができます。
if((n & 1) == 0) std::cout << "n は偶数です。" << std::endl;
しかし、このif文で実行される命令がいつまでも一つとは限りません。またelseが追加されることもあります。 こういったときに起こりがちなバグが中括弧の入れ忘れです。この対策として下の例のように常に中括弧を入れるというものがあります。
if((n & 1) == 0) { std::cout << "n は偶数です。" << std::endl; }
また同様にenumを使う際にも最後の定数名の後に","をつけることで追加したときに","を忘れてもコンパイルエラーが出なくなります。
ソースコード中に突然出てくる定数のことをマジックナンバーといいます。 たとえばキャラクターの移動などを制限するため以下のようなコードを書くことが良くあると思います。
if (value < 0) { y = 0; } else if (value > 480) { y = 480; } else { y = value; }
このとき 0 や 480 などがマジックナンバーであり、(定数)変数で置き換えるべきものです。これらの定数を変数で置換することによって、定数の変更忘れがなくなります。
const int minY = 0; const int maxY = 480; if (value < minY) { y = minY; } else if (value > maxY) { y = maxY; } else { y = value; }
mallocやnewなどで確保した領域のポインタに対して多重にfreeやdeleteを行うことは許されていません。
解放した後のポインタには必ずNULLを代入すべきです。NULLに対してfreeやdeleteを行っても何も起こりません。 以下のようなマクロを使うことで簡単に記述できます。
#define DELETE(p) { delete(p); (p) = NULL; }
#defineなどのマクロはエラーメッセージがわかりづらく、理解しがたいバグを引き起こす可能性があるのであまり使わないようにしましょう。
#defineの変わりに定数変数を使うことで、エラーメッセージの中にその変数名がでてきてデバッグしやすくなります。
一つのファイルにすべてを記述するのではなく機能ごとや処理対象ごとにソースコードを分割します。
文字列に対する処理などは、思ったよりも多くの関数が標準で用意されています。
同等の機能を自分で新たに書き直すのではなく、可能な限り標準の関数を利用するようにしましょう。
std::swap、std::max、std::maxなどはすぐにでも使える便利な関数だと思います。
C や C++ においてポインタの扱いは非常に難しくバグの温床となっています。なので可能な限り使わないべきだと思います。
C++にはスマートポインタと呼ばれる自動的にdeleteを呼び出してくれるポインタがあります。
auto_ptrやshared_ptrなどの種類があります。 後者はBoostライブラリを導入することで使えるようになりますが、Visual Studio2008からは標準のライブラリの中に含まれるようになりました。
#include <iostream> #include <memory> class Destructable { public: Destructable(){} ~Destructable() { std::cout << "Object is Destructed." << std::endl; } }; int main() { const std::auto_ptr<Destructable> smart_ptr(new Destructable()); return 0; }
#include <iostream> #include <memory> class Destructable { public: Destructable(){} ~Destructable() { std::cout << "Object is Destructed." << std::endl; } }; int main() { std::tr1::shared_ptr<Destructable> smart_ptr(new Destructable()); return 0; }
C++には参照という機能があります。これは変数の種類の一つであり、ポインタを直接操作することなく、参照先の変数の値を変更することができます。
下記にポインタを使ったswap関数を示します。
void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; }
以下に参照を使ったswap関数を示します。
void swap(int &a, int &b) { int temp = a; a = b; b = temp; }
関数の引数名の前に"&"をつけることでポインタを使うことなく同等の機能を利用することができます。
基本的に配列を使うよりはVector(可変長の配列)を使ったほうが良いです。 その他STLには便利なコンテナやアルゴリズムがたくさんあります。
関数ポインタを使うよりも継承を用いたほうが安全です。