Aritalab:Lecture/Programming/Cpp/Tips

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

Personal tools
Namespaces

Variants
Actions
Navigation
metabolites
Toolbox