◆ C++での記述
if (i++ < 10) Hoge(i)
◆ 生成されるアセンブラコード
mov ebx, eax inc eax cmp ebx, 10 jnc L1 push eax call Hoge L1:
◆ C++での記述
if (++i < 11) Hoge(i);
◆ 生成されるアセンブラコード
inc eax cmp eax, 11 jnc L1 push eax call Hoge L1:
※実際には、この程度のコードならほとんどのコンパイラは最適化が可能なので、実行時の差異は生じません。
※生成されるアセンブラはイメージです。実際にはコンパイラによって生成されるコードは異なります。
◆ C++での記述 (後置き++の場合)
CFoo foo; if (foo++ < 10) Hoge(foo)
◆ インライン展開されるコード
CFoo tmp = foo; foo.m_value.plus1(); if (CFoo::operator < (tmp.m_value, 10)) { Hoge(foo) }
◆ C++での記述 (前置き++の場合)
CFoo foo; if (++foo < 11) Hoge(foo);
◆ インライン展開されるコード
if (CFoo::operator < (foo.m_value.plus1() , 11)) { Hoge(foo) }
CFooの実装は以下のようになる。
struct CValue { CValue & plus1(); } bool operator < (const CValue&, int); struct CFoo { CValue m_value; CFoo() {} bool operator < (int n) { return m_value < n; } CFoo& operator ++() { m_value .plus1(); return *this; } CFoo operator ++(int) { CFoo tmp = *this; //<- オブジェクトの生成とコピーが発生 m_value .plus1(); return tmp; //<- オブジェクトの生成とコピーが発生 } }
STLのvector<int>とmap<int,int>のiteratorをインクリメント(++)する実行時間を、前置きと後置きで比較してみました。
オブジェクト | map<> iterator++ | map<> ++iterator | vector<> iterator++ | vector<> ++iterator |
実行時間(Releaseビルド) | 1.300815 | 0.300459 | 0.567246 | 0.566541 |
比率 | 100.00% | 23.10% | 100.00% | 99.98% |
実行時間(Debugビルド) | 1.361722 | 0.108110 | 1.203101 | 0.157290 |
比率 | 100.0% | 7.94% | 100.00% | 13.07% |
この結果を見ても、意味のない i++ を書きますか?
※測定環境 Athlon64 3.0GHz x2 VisualStudio 2009