понедельник, февраля 14, 2011

Статья с сравнением ++it и it++

В статье Есть ли практический смысл использовать для итераторов префиксный оператор инкремента ++it, вместо постфиксного it++ Андрей Карпов ставит эксперименты с префиксными и постфисными операторами.

18 коммент.:

Sergey Miryanov комментирует...

Алена, должно быть стыдно давать ссылки на такую ерунду.

gnawer комментирует...

Я ++it вообще не использую принципиально. Потому что это малопонятная для человека конструкция, а язык программирования создавался для того, чтобы человек понимал, а не железяка. Да и мало кто использует, разве что кто её только изучил и хочет поприменять, после чего все вокруг страшно матерятся. Статья впрочем интересная с точки зрения что и на этих спичках можно как-то сэкономить.

Анонимный комментирует...

gnawer, а почему по-вашему гугл это рекомендует?

Marat комментирует...

gnawer: Я ++it вообще не использую принципиально. Потому что это малопонятная для человека конструкция, а язык программирования создавался для того, чтобы человек понимал, а не железяка.
Конструкция it++ мне от чего-то не кажется более понятной, чем ++it. Эту тему я для себя давно закрыл - пишу it++ (только) тогда, когда требуется предыдущее значение it (практически никогда - это уже смахивает на tricky code). В остальных случаях - только ++it. На C++ лучше писать то, что действительно хочешь получить (и ни грамма лишнего), тогда твои желания (потенциально) не будут идти вразрез с тем, что заложено в компилятор.

pilote d' essai комментирует...

Почему ерунда-то?
А с Маратом я согласен

Андрей Валяев комментирует...

А я, в последнее время, предпочитаю BOOST_FOREACH. Он избавляет меня от головной боли на тему с какой стороны поставить ++ :)

С вектором ситуация, в процессе оптимизации, возможно и сводится к тривиальной возне с указателями. Но итераторы бывают разные... Так что ++С все таки правильнее использовать.

Голубцов Антон комментирует...

Статейка занятная, только одно "НО" каждый раз при обсуждении рассматриваются просто вектор.
у которого итератор в релизе = указатель.
а если это map, а если это самописный контейнер со сложной логикой переходов между элементами или создание временного объекта сама по себе тяжелая операция, задачи-то у всех разные и объекты разные. В статье релизный вектор можно было смело заменить обычный массив и в релизе бы ничего не изменилось.

Dmitriy комментирует...

у Саттера с Александреску есть замечательная книга "C++ Coding Standards". Там даётся хорошее определение преждевременной оптимизации и "пессимизации" кода. Так вот, использование постфиксной формы операторов в местах, где подходит префиксная, авторы классифицируют как пессимизация, т.к. при одинаковых накладных расходах (сложность написания кода, его последующая поддержка и т.д.) получаем потенциально более медленный код.

Я бы от себя добавил, что при использовании этого принципа, глаза всегда "цепляются" за постфиксную форму. Ведь если автор кода её использовал, значит префиксная форма не подходит, значит, в этом месте надо быть повнимательнее.

Хотел запостить коммент на Хабре, но там как-то сложно получить аккаунт.

le_cha_sever комментирует...

Решил проверить у себя на реальной программе для микроконтроллеров. Примерно 6к кода, 29 случаев ++/--.
В резальтате код уменьшился на 4 байта, скорость работы не мерял, так как раз тут оно и не критично (да и не реально на фоне записи во флешь увидеть разницу).

le_cha_sever комментирует...

Да, забыл указать, компилятор SDCC

SVGreg комментирует...

@Sergey Miryanov +1
@Dmitriy +1

Действительно статья на хабре бестолковая. Не вижу смысла сравнивать на скорость эти операторы, т.к. они используются в различных ситуациях. А при скорости современных ПК обращать внимание стоит только на суть возвращаемого значения.

Анонимный комментирует...

Кстати, если кому интересно как на низком уровне, то разница на примере целымх (int) будет такой

k++; vs. ++k;

int k = 1;
; Line 4
mov DWORD PTR _k$[ebp], 1

k++;
; Line 5
mov eax, DWORD PTR _k$[ebp]
add eax, 1
mov DWORD PTR _k$[ebp], eax

++k;
; Line 6
mov ecx, DWORD PTR _k$[ebp]
add ecx, 1
mov DWORD PTR _k$[ebp], ecx

Собственно разница в используемом регистре: eax для k++ и ecx для ++k. Данные получены в cl /Fa (Visual C++).

Кстати разница между s *= p; и s = s*p; так же будет такой (в регистре), только операции соответственные.
А вот для более сложных объектов (вроде Вектора) имеет смысл уже выбирать (и ++it будет действительно предпочительнее по скорости).

Alexcnt комментирует...

Привет всем, сейчас попробовал дизассемблировать через IDA PRO 2 объектных файла:
1)
void main()
{
int x = 1;
x++;
}

2)
void main()
{
int x = 1;
++x;
}

В коде следующее:

_main proc near

var_CC= byte ptr -0CCh
var_8= dword ptr -8

push ebp
mov ebp, esp
sub esp, 0CCh
push ebx
push esi
push edi
lea edi, [ebp+var_CC]
mov ecx, 33h ; '3'
mov eax, 0CCCCCCCCh
rep stosd
mov [ebp+var_8], 1
mov eax, [ebp+var_8]
add eax, 1
mov [ebp+var_8], eax
xor eax, eax
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
retn
_main endp


Как для первого, так и для второго случая, различий не нашел, компилятор VS 2010.

Alexcnt комментирует...

Получается, что компилятор сам распоряжается каким регистром ему в данном случае воспользоваться?

Alena комментирует...

Alexcnt
Получается, что компилятор сам распоряжается каким регистром ему в данном случае воспользоваться?

Создатели компилятора сами решают как им чего оптимизировать. Главное, чтобы оно Стандарту соответствовало.

Alexcnt комментирует...

Спасибо большое, разобрался: вся оптимизация на уровне машинных команд зависит от компилятора.
Кстати, кому интересно, по данной теме есть забавная статья http://blog.emptycrate.com/node/329

В социальной сети поместил опросник, получил следующие результаты для разных компиляторов:

1)
VS 2010
4, 5, 2, 5
12
12

2)
gcc 4.4.5
4, 5, 2, 5
9
9

3)
GNU C++ 4
4, 5, 2, 5
9
9

4)
MS Visual C++ 2005
3, 3, 2, 3
12
12

5)
Borland C++ 3.1
4, 4, 2, 2
12
12

6)
MS Visual C++ 1998
1,1,0,1
11
11

7)
Dev C++ v4
4,4,2,2
9
9

Alexcnt комментирует...

Алёна, скинул ссылку на ваш блог в ЖЖ (в своей первой статье)
http://alexcnt.livejournal.com/619.html

Alexcnt комментирует...

По привычке уже пишу Алёна))