Ответ 1
В конкретном случае std::vector
в реализации GNU GCC STL (версия 4.6.1) я не думаю, что на достаточно высоких уровнях оптимизации будет разница в производительности.
Реализация для итераторов вперед на vector
предоставляется __gnu_cxx::__normal_iterator<typename _Iterator, typename _Container>
. Давайте посмотрим на его конструктор и постфикс ++
:
explicit
__normal_iterator(const _Iterator& __i) : _M_current(__i) { }
__normal_iterator
operator++(int)
{ return __normal_iterator(_M_current++); }
И его экземпляр в vector
:
typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;
Как вы можете видеть, он внутренне выполняет приращение постфикса на обычном указателе, а затем передает исходное значение через свой собственный конструктор, который сохраняет его локальному элементу. Этот код должен быть тривиальным для устранения посредством анализа мертвых значений.
Но действительно ли он оптимизирован? Пусть узнают. Тестовый код:
#include <vector>
void test_prefix(std::vector<int>::iterator &it)
{
++it;
}
void test_postfix(std::vector<int>::iterator &it)
{
it++;
}
Выходная сборка (на -Os
):
.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
в частности префикс и постфикс (без учета возвращаемого значения postfix) имеют одинаковую производительность.