Aritalab:Lecture/Programming/Cpp/Tips
From Metabolomics.JP
< Aritalab:Lecture | Programming | Cpp(Difference between revisions)
m |
|||
Line 2: | Line 2: | ||
=C++プログラムのコツ= | =C++プログラムのコツ= | ||
− | + | ||
+ | ===マクロは書かない=== | ||
+ | Cプログラマがマクロを使って得られたメリットのほぼ全てが、テンプレートやconst指定を使って実現可能です。 | ||
+ | 型チェックをすり抜けるマクロの利用はできる限り避けてください。 | ||
+ | マクロについては、[[Aritalab:Lecture/Programming/Cpp/Macro|書き方のページ]]を参考にしてください。 | ||
===巨大な配列はヒープ領域に確保する=== | ===巨大な配列はヒープ領域に確保する=== | ||
Line 12: | Line 16: | ||
| | | | ||
<pre> | <pre> | ||
+ | /* 問題なく動く */ | ||
int* array = new int[1000000]; | int* array = new int[1000000]; | ||
</pre> | </pre> | ||
| | | | ||
<pre> | <pre> | ||
+ | /* overflowを起して動かない */ | ||
int array[1000000]; | int array[1000000]; | ||
</pre> | </pre> | ||
|} | |} | ||
− | プログラムが利用するメモリには、new/delete(malloc/free) | + | |
+ | プログラムが利用するメモリには、new/delete(malloc/free)で確保されるヒープ領域と、関数呼び出しや変数の利用で確保されるスタック領域があります。 | ||
+ | |||
+ | 通常、ヒープ領域には大きなスペースが確保されていますが、スタック領域は1MB程度しかありません。プログラム中で大きな配列を(自動変数として)定義するとすぐにStack overflow errorを起こします。大きな配列はnewで確保しましょう。 | ||
===イテレータのインクリメントは前置にする=== | ===イテレータのインクリメントは前置にする=== | ||
Line 44: | Line 53: | ||
</pre> | </pre> | ||
|} | |} | ||
− | + | 基本データ型でない場合、インクリメント演算子の定義は以下のようになります。戻り値の型に注意してください。後置オペレータは処理の後にインクリメントするため、返り値をインクリメントする前の状態にしないといけません。 | |
{| | {| | ||
|width="40%"| | |width="40%"| | ||
Line 52: | Line 61: | ||
iterator _Tmp = *this; | iterator _Tmp = *this; | ||
++*this; | ++*this; | ||
− | return _Tmp; | + | return _Tmp; // ここでインクリメント前の値を返す |
} | } | ||
Line 62: | Line 71: | ||
</pre> | </pre> | ||
|} | |} | ||
− | + | ||
− | + | この理由で、後置オペレータではオーバーロードする関数内でコピーコンストラクタによるオブジェクトの作成と、作成したオブジェクトを戻す際に再びコピーと、余分にオブジェクトが作成されるのです。 | |
+ | 余分な処理を除くため、前置インクリメントを使います。(ただし、基本データタイプについてはどちらでも効率は同じです。) | ||
===改行はendlではなく、"\n"を出力する=== | ===改行はendlではなく、"\n"を出力する=== |
Revision as of 14:12, 13 October 2010
Wiki Top | Up one level | レポートの書き方 | Arita Laboratory |
|
C++プログラムのコツ
マクロは書かない
Cプログラマがマクロを使って得られたメリットのほぼ全てが、テンプレートやconst指定を使って実現可能です。 型チェックをすり抜けるマクロの利用はできる限り避けてください。 マクロについては、書き方のページを参考にしてください。
巨大な配列はヒープ領域に確保する
Good | Bad |
---|---|
/* 問題なく動く */ int* array = new int[1000000]; |
/* overflowを起して動かない */ int array[1000000]; |
プログラムが利用するメモリには、new/delete(malloc/free)で確保されるヒープ領域と、関数呼び出しや変数の利用で確保されるスタック領域があります。
通常、ヒープ領域には大きなスペースが確保されていますが、スタック領域は1MB程度しかありません。プログラム中で大きな配列を(自動変数として)定義するとすぐにStack overflow errorを起こします。大きな配列はnewで確保しましょう。
イテレータのインクリメントは前置にする
Good | Bad |
---|---|
vector<string> V; : for(vector<string>::iterator itr=V.begin(); itr != V.end(); ++itr) cout << *itr << "\n"; |
vector<string> V; : for(vector<string>::iterator itr=V.begin(); itr != V.end(); itr++) cout << *itr << "\n"; |
基本データ型でない場合、インクリメント演算子の定義は以下のようになります。戻り値の型に注意してください。後置オペレータは処理の後にインクリメントするため、返り値をインクリメントする前の状態にしないといけません。
iterator operator++(int) { //後置 iterator _Tmp = *this; ++*this; return _Tmp; // ここでインクリメント前の値を返す } iterator& operator++() { //前置 ++*this; return *this; } |
この理由で、後置オペレータではオーバーロードする関数内でコピーコンストラクタによるオブジェクトの作成と、作成したオブジェクトを戻す際に再びコピーと、余分にオブジェクトが作成されるのです。 余分な処理を除くため、前置インクリメントを使います。(ただし、基本データタイプについてはどちらでも効率は同じです。)
改行はendlではなく、"\n"を出力する
Good | Bad |
---|---|
out << "\n"; |
out << endl; |
endlを出力する操作は、out << "\n"; out.flush();と同じです。頻繁に利用する場合は、flushの分だけ前者のほうが効率が良くなります。