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

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

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

18 комментариев:

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

    ОтветитьУдалить
  2. Анонимный14/2/11 08:42

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

    ОтветитьУдалить
  3. Анонимный14/2/11 08:55

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

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

    ОтветитьУдалить
  5. Почему ерунда-то?
    А с Маратом я согласен

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

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

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

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

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

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

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

    ОтветитьУдалить
  10. Да, забыл указать, компилятор SDCC

    ОтветитьУдалить
  11. @Sergey Miryanov +1
    @Dmitriy +1

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

    ОтветитьУдалить
  12. Анонимный16/2/11 02:13

    Кстати, если кому интересно как на низком уровне, то разница на примере целымх (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 будет действительно предпочительнее по скорости).

    ОтветитьУдалить
  13. Привет всем, сейчас попробовал дизассемблировать через 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.

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

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

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

    ОтветитьУдалить
  16. Спасибо большое, разобрался: вся оптимизация на уровне машинных команд зависит от компилятора.
    Кстати, кому интересно, по данной теме есть забавная статья 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

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

    ОтветитьУдалить
  18. По привычке уже пишу Алёна))

    ОтветитьУдалить