Вот пример для случая, когда операторы приращения находятся в разных единицах перевода. Компилятор с g ++ 4.5.
На данный момент игнорируем проблемы со стилем
// a.cc
#include <ctime>
#include <array>
class Something {
public:
Something& operator++();
Something operator++(int);
private:
std::array<int,PACKET_SIZE> data;
};
int main () {
Something s;
for (int i=0; i<102430; ++i) ++s; // warm up
std::clock_t a = clock();
for (int i=0; i<1024*1024*30; ++i) ++s;
a = clock() - a;
for (int i=0; i<1024*1024*30; ++i) s++; // warm up
std::clock_t b = clock();
for (int i=0; i<1024*1024*30; ++i) s++;
b = clock() - b;
std::cout << "a=" << (a/double(CLOCKS_PER_SEC))
<< ", b=" << (b/double(CLOCKS_PER_SEC)) << '\n';
return 0;
}
O (n) приращение
Test
// b.cc
#include <array>
class Something {
public:
Something& operator++();
Something operator++(int);
private:
std::array<int,PACKET_SIZE> data;
};
Something& Something::operator++()
{
for (auto it=data.begin(), end=data.end(); it!=end; ++it)
++*it;
return *this;
}
Something Something::operator++(int)
{
Something ret = *this;
++*this;
return ret;
}
Результаты
Результаты (время в секундах) с g ++ 4.5 на виртуальной машине:
Flags (--std=c++0x) ++i i++
-DPACKET_SIZE=50 -O1 1.70 2.39
-DPACKET_SIZE=50 -O3 0.59 1.00
-DPACKET_SIZE=500 -O1 10.51 13.28
-DPACKET_SIZE=500 -O3 4.28 6.82
O (1) приращение
Тест
Давайте теперь возьмем следующий файл:
// c.cc
#include <array>
class Something {
public:
Something& operator++();
Something operator++(int);
private:
std::array<int,PACKET_SIZE> data;
};
Something& Something::operator++()
{
return *this;
}
Something Something::operator++(int)
{
Something ret = *this;
++*this;
return ret;
}
*1024* Это ничего не делает в приращении. Это моделирует случай, когда приращение имеет постоянную сложность.
Результаты
Результаты теперь сильно различаются:
Flags (--std=c++0x) ++i i++
-DPACKET_SIZE=50 -O1 0.05 0.74
-DPACKET_SIZE=50 -O3 0.08 0.97
-DPACKET_SIZE=500 -O1 0.05 2.79
-DPACKET_SIZE=500 -O3 0.08 2.18
-DPACKET_SIZE=5000 -O3 0.07 21.90
Заключение
Производительность мудр
Если вам не нужно предыдущее значение, установите привычку использовать предварительное увеличение. Будьте последовательны даже со встроенными типами, вы привыкнете к этому и не рискуете понести ненужную потерю производительности, если когда-нибудь замените встроенный тип на пользовательский тип.
Семантический-накрест
i++
говорит increment i, I am interested in the previous value, though
.
++i
говорит increment i, I am interested in the current value
или increment i, no interest in the previous value
. Опять же, вы привыкнете к этому, даже если не сейчас.
Кнут.
Преждевременная оптимизация - корень всего зла. Как и преждевременная пессимизация.