Aritalab:Lecture/Programming/Cpp/Tips
From Metabolomics.JP
< Aritalab:Lecture | Programming | Cpp(Difference between revisions)
Line 1: | Line 1: | ||
− | + | =C++プログラムのコツ= | |
+ | __FORCETOC__ | ||
− | + | ===巨大な配列はヒープ領域に確保する=== | |
− | + | ||
+ | {| | ||
+ | |width="40%"| Good | ||
+ | <pre> | ||
+ | int* array = new int[1000000]; | ||
+ | </pre> | ||
+ | |width="40%"| Bad | ||
<pre> | <pre> | ||
− | + | int array[1000000]; | |
− | + | ||
</pre> | </pre> | ||
− | + | |} | |
− | + | プログラムが利用するメモリには、new/delete(malloc/free)で確保されるヒープ領域と、関数呼び出しや変数の利用で確保されるスタック領域があります。スタック領域は1MB程度しかないので、大きな配列を確保するとすぐにStack overflow errorを起こします。大きな配列はnewで確保しましょう。 | |
− | < | + | |
+ | ===イテレータのインクリメントは前置にする=== | ||
+ | {| | ||
+ | |width="40%"| Good | ||
+ | <pre> | ||
+ | for(vector<string>::iterator itr=V.begin(); | ||
+ | itr != V.end(); ++itr) | ||
+ | cout << *itr << "\n"; | ||
+ | </pre> | ||
+ | |width="40%"| Bad | ||
+ | <pre> | ||
+ | for(vector<string>::iterator itr=V.begin(); | ||
+ | itr != V.end(); itr++) | ||
+ | cout << *itr << "\n"; | ||
+ | </pre> | ||
+ | |} | ||
基本データ型でない場合、インクリメント演算子の定義は以下のようになります。戻り値の型に注意してください。後置オペレータは処理の後にインクリメントするため、返り値がインクリメントする前の状態にしないといけません。 | 基本データ型でない場合、インクリメント演算子の定義は以下のようになります。戻り値の型に注意してください。後置オペレータは処理の後にインクリメントするため、返り値がインクリメントする前の状態にしないといけません。 | ||
+ | {| | ||
+ | |width="40%"| | ||
<pre> | <pre> | ||
iterator operator++(int) | iterator operator++(int) | ||
Line 26: | Line 49: | ||
} | } | ||
</pre> | </pre> | ||
+ | |} | ||
このためオーバーロードする関数の中でコピーコンストラクタによるオブジェクトの作成と、作成したオブジェクトを戻す際に再びコピーと、余分にオブジェクトが作成されるのです。 | このためオーバーロードする関数の中でコピーコンストラクタによるオブジェクトの作成と、作成したオブジェクトを戻す際に再びコピーと、余分にオブジェクトが作成されるのです。 | ||
こうした余分な処理を含まないため、前置インクリメントを使います。(ただし、基本データタイプについてはどちらでも同じです。) | こうした余分な処理を含まないため、前置インクリメントを使います。(ただし、基本データタイプについてはどちらでも同じです。) | ||
+ | |||
+ | ===改行は"\n"を出力する=== | ||
+ | {| | ||
+ | |width="40%"| Good | ||
+ | <pre>out << "\n";</pre> | ||
+ | |width="40%"| Bad | ||
+ | <pre>out << endl;</pre> | ||
+ | |} | ||
+ | <tt>endl</tt>を出力する操作は、<tt>out << "\n"; out.flush();</tt>と同じです。頻繁に利用する場合は、flushの分だけ前者のほうが効率が良くなります。 |
Revision as of 22:52, 7 October 2010
Contents |
C++プログラムのコツ
巨大な配列はヒープ領域に確保する
Good
int* array = new int[1000000]; |
Bad
int array[1000000]; |
プログラムが利用するメモリには、new/delete(malloc/free)で確保されるヒープ領域と、関数呼び出しや変数の利用で確保されるスタック領域があります。スタック領域は1MB程度しかないので、大きな配列を確保するとすぐにStack overflow errorを起こします。大きな配列はnewで確保しましょう。
イテレータのインクリメントは前置にする
Good
for(vector<string>::iterator itr=V.begin(); itr != V.end(); ++itr) cout << *itr << "\n"; |
Bad
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; } |
このためオーバーロードする関数の中でコピーコンストラクタによるオブジェクトの作成と、作成したオブジェクトを戻す際に再びコピーと、余分にオブジェクトが作成されるのです。 こうした余分な処理を含まないため、前置インクリメントを使います。(ただし、基本データタイプについてはどちらでも同じです。)
改行は"\n"を出力する
Good
out << "\n"; |
Bad
out << endl; |
endlを出力する操作は、out << "\n"; out.flush();と同じです。頻繁に利用する場合は、flushの分だけ前者のほうが効率が良くなります。