В статье Есть ли практический смысл использовать для итераторов префиксный оператор инкремента ++it, вместо постфиксного it++ Андрей Карпов ставит эксперименты с префиксными и постфисными операторами.
My Nutty, Extremist Beliefs
10 часов назад
18 коммент.:
Алена, должно быть стыдно давать ссылки на такую ерунду.
Я ++it вообще не использую принципиально. Потому что это малопонятная для человека конструкция, а язык программирования создавался для того, чтобы человек понимал, а не железяка. Да и мало кто использует, разве что кто её только изучил и хочет поприменять, после чего все вокруг страшно матерятся. Статья впрочем интересная с точки зрения что и на этих спичках можно как-то сэкономить.
gnawer, а почему по-вашему гугл это рекомендует?
gnawer: Я ++it вообще не использую принципиально. Потому что это малопонятная для человека конструкция, а язык программирования создавался для того, чтобы человек понимал, а не железяка.
Конструкция it++ мне от чего-то не кажется более понятной, чем ++it. Эту тему я для себя давно закрыл - пишу it++ (только) тогда, когда требуется предыдущее значение it (практически никогда - это уже смахивает на tricky code). В остальных случаях - только ++it. На C++ лучше писать то, что действительно хочешь получить (и ни грамма лишнего), тогда твои желания (потенциально) не будут идти вразрез с тем, что заложено в компилятор.
Почему ерунда-то?
А с Маратом я согласен
А я, в последнее время, предпочитаю BOOST_FOREACH. Он избавляет меня от головной боли на тему с какой стороны поставить ++ :)
С вектором ситуация, в процессе оптимизации, возможно и сводится к тривиальной возне с указателями. Но итераторы бывают разные... Так что ++С все таки правильнее использовать.
Статейка занятная, только одно "НО" каждый раз при обсуждении рассматриваются просто вектор.
у которого итератор в релизе = указатель.
а если это map, а если это самописный контейнер со сложной логикой переходов между элементами или создание временного объекта сама по себе тяжелая операция, задачи-то у всех разные и объекты разные. В статье релизный вектор можно было смело заменить обычный массив и в релизе бы ничего не изменилось.
у Саттера с Александреску есть замечательная книга "C++ Coding Standards". Там даётся хорошее определение преждевременной оптимизации и "пессимизации" кода. Так вот, использование постфиксной формы операторов в местах, где подходит префиксная, авторы классифицируют как пессимизация, т.к. при одинаковых накладных расходах (сложность написания кода, его последующая поддержка и т.д.) получаем потенциально более медленный код.
Я бы от себя добавил, что при использовании этого принципа, глаза всегда "цепляются" за постфиксную форму. Ведь если автор кода её использовал, значит префиксная форма не подходит, значит, в этом месте надо быть повнимательнее.
Хотел запостить коммент на Хабре, но там как-то сложно получить аккаунт.
Решил проверить у себя на реальной программе для микроконтроллеров. Примерно 6к кода, 29 случаев ++/--.
В резальтате код уменьшился на 4 байта, скорость работы не мерял, так как раз тут оно и не критично (да и не реально на фоне записи во флешь увидеть разницу).
Да, забыл указать, компилятор SDCC
@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 будет действительно предпочительнее по скорости).
Привет всем, сейчас попробовал дизассемблировать через 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
Получается, что компилятор сам распоряжается каким регистром ему в данном случае воспользоваться?
Создатели компилятора сами решают как им чего оптимизировать. Главное, чтобы оно Стандарту соответствовало.
Спасибо большое, разобрался: вся оптимизация на уровне машинных команд зависит от компилятора.
Кстати, кому интересно, по данной теме есть забавная статья 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
Алёна, скинул ссылку на ваш блог в ЖЖ (в своей первой статье)
http://alexcnt.livejournal.com/619.html
По привычке уже пишу Алёна))
Отправить комментарий