、私は十分に高い最適化レベルでのパフォーマンスの違いがあるとは思いません。
vector
のフォワードイテレータの実装は、__gnu_cxx::__normal_iterator<typename _Iterator, typename _Container>
で提供されています。のは、そのコンストラクタと後置++
オペレータを見てみましょう:
vector
で
explicit
__normal_iterator(const _Iterator& __i) : _M_current(__i) { }
__normal_iterator
operator++(int)
{ return __normal_iterator(_M_current++); }
とそのインスタンス化:
typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;
あなたが見ることができるように、それは内部的に通常のポインタの後置インクリメントを行い、その後、元を渡します独自のコンストラクタを使用して値をローカルメンバーに保存します。このコードは、デッド・バリュー分析を通じて排除するのは簡単なことです。
本当に最適化されていますか?確認してみましょう。テストコード:(-Os
上)
#include <vector>
void test_prefix(std::vector<int>::iterator &it)
{
++it;
}
void test_postfix(std::vector<int>::iterator &it)
{
it++;
}
出力アセンブリ:
.file "test.cpp"
.text
.globl _Z11test_prefixRN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE
.type _Z11test_prefixRN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE, @function
_Z11test_prefixRN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE:
.LFB442:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 8(%ebp), %eax
addl $4, (%eax)
popl %ebp
.cfi_def_cfa 4, 4
.cfi_restore 5
ret
.cfi_endproc
.LFE442:
.size _Z11test_prefixRN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE, .-_Z11test_prefixRN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE
.globl _Z12test_postfixRN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE
.type _Z12test_postfixRN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE, @function
_Z12test_postfixRN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE:
.LFB443:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 8(%ebp), %eax
addl $4, (%eax)
popl %ebp
.cfi_def_cfa 4, 4
.cfi_restore 5
ret
.cfi_endproc
.LFE443:
.size _Z12test_postfixRN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE, .-_Z12test_postfixRN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE
.ident "GCC: (Debian 4.6.0-10) 4.6.1 20110526 (prerelease)"
.section .note.GNU-stack,"",@progbits
あなたが見ることができるように、まったく同じアセンブリは、両方のケースで出力されます。
もちろん、これは必ずしもカスタムイテレータやより複雑なデータ型の場合には当てはまりません。しかし、具体的には、vector
の場合、接頭辞と接尾辞(接尾辞の戻り値を取り込まない)は同じ性能を持つように見えます。
**は**マイクロ最適化であっても興味深い質問です。 – jpm
反復子操作で副作用が発生しない限り、コンパイラは* as-if *規則に従って最適化された更新後のバージョンを使用できます。それがコンパイラに依存するかどうか。 Indebugビルド、それはおそらく最適化されないでしょう、なぜデバッグを遅くするのですか?あなたが実際にそれを必要とするときにだけポストインクリメントを使う良い習慣を開発するという問題はありません。 –
@Gene私は同意します。私はいつでもプリインクリメントを使用する習慣があります。私はちょうど興味があります:) –