Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.76/165: Рейтинг темы: голосов - 165, средняя оценка - 4.76
8 / 8 / 0
Регистрация: 17.04.2010
Сообщений: 112
1

Разница между префиксной и постфиксной формой записи счетчика цикла

26.04.2010, 17:56. Показов 30779. Ответов 57
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте!

Когда оформлял циклы всегда использовал такую запись:

C++
1
for(int i=0; i<10; i++)
, которая означает что цикл будет выполнен не более 10 раз, счетчик будет увеличен только после выполнения тела цикла и успешного выполнения условия(i<10).

В последнее время стал встречать другую запись:
C++
1
for(int i=0; i<10; ++i)
В чем принципиальное различие этих форм записей для использования цикла?
Когда какой более предпочтителен?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.04.2010, 17:56
Ответы с готовыми решениями:

Перегрузка постфиксной и префиксной операции инкремента
Здравствуйте! У меня возник вопрос: почему выводит разный результат, казалось бы, одинаковый код ...

Перегрузка постфиксной и префиксной формы оператора ++
доброго времени суток форумчане, у меня такой вопрос, как перегрузить оператор ++ все другие...

Отличие постфиксной и префиксной формы декрементирования при работе с массивами
Здравствуйте. Есть код, который работает(префиксная форма): #include &lt;stdio.h&gt; int...

Разница между вариантами цикла
Занимаюсь по книге Шилдт Г. - Java 8. Руководство для начинающих - 2015. Прохожу цикл FOR, был...

57
9 / 9 / 0
Регистрация: 22.01.2012
Сообщений: 59
12.08.2014, 14:04 21
Author24 — интернет-сервис помощи студентам
taras atavin, kazak, не совсем так. Для базовых типов оптимизатор (если он, конечно, у вас включен) i++ преобразует в ++i, где это возможно. Однако, для итераторов это не верно, так что есть люди, которые всегда используют ++i для сохранения целостности кода. Однако мне кажется, что i++ все-таки выглядит приятнее.

немного я опоздал с ответом)

по поводу скорости работы:
i++ в простейшем виде:
tmp = i;
++i;
return tmp;
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
17.08.2014, 06:57 22
Цитата Сообщение от Андрей Xomach Посмотреть сообщение
aras atavin, kazak, не совсем так. Для базовых типов оптимизатор (если он, конечно, у вас включен) i++ преобразует в ++i, где это возможно.
И это у Вас считается аргументом за идентичность операторов? Раз приходится заменять один на другой, значит они уже не равны и оптимальней тот, на который меняет оптимизатор. Причём, он ведь может быть как просто выключен, так и может потом возникнуть необходимость в замене типа на не базовый. Кроме того, сама замена отнимает время компиляции и если прогер привык писать ++i, то тем самым оптимизирует уже этот этап.
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
17.08.2014, 12:09 23
Цитата Сообщение от QenT Посмотреть сообщение
лучше сделать как по стандарту i++
Страуструп в цикле постоянно использует преинкремент (см. Bjarne Stroustrup - The C++ Programming Language - 2013, Fourth Edition, 9.5 Iteration Statements).
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
19.08.2014, 19:21 24
Цитата Сообщение от QenT Посмотреть сообщение
и в цикле лучше сделать как по стандарту i++)
Вот только в стандарте описаны оба оператора.

Добавлено через 5 минут
Цитата Сообщение от QenT Посмотреть сообщение
Сам очень много делал тестов с ними, и обоими руками за то, что бы не использовать префиксы и постфиксы в присваивании, уже через пару дней, после написания кода, можно забыть и самому, что ты хотел, а другие и подавно не догадаются!
А там нечего догадываться, всё легко читается. Как раз i=i+1 заставляет гадать, что хотел ещё прикрутить к этому выражению, так как ни кто не думает в терминах "присвоить переменной i сумму i и 1", а вот "увеличить i на 1" - это как раз вполне нормальная мысль и на c++ переводится как ++i. Заметьте, не "i увеличить", а "увеличить i", то есть действие впереди операнда и чтоб их переставить в i++ нужно дополнительное время, хоть и не заметное. А неуклюжее i=i+1 читается и не вызывает необходимости догадываться только на бейсике и ему подобных языках, где инкремента нет.
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
19.08.2014, 19:35 25
Цитата Сообщение от taras atavin Посмотреть сообщение
стандарте описаны оба оператора
Описаны оба, конечно. Вопрос о том, какой именно инкремент (пре- или пост-) лучше (эффективнее, красивее, по фен-шую, по науке, правильнее - подставь свой вариант) в циклах использовать.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
19.08.2014, 19:39 26
Префиксный, так как постфиксный именно к нему и оптимизируется.
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
19.08.2014, 19:58 27
Цитата Сообщение от taras atavin Посмотреть сообщение
Префиксный, так как постфиксный именно к нему и оптимизируется.
Согласен, я тоже считаю, что префиксный инкремент в циклах соответствует духу Дзен. Но тут есть противники такой позиции
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
19.08.2014, 20:00 28
Цитата Сообщение от QenT Посмотреть сообщение
лучше сделать как по стандарту
Согласен. Посмотрим, как же в стандарте в циклах юзают инкремент:
Миниатюры
Разница между префиксной и постфиксной формой записи счетчика цикла   Разница между префиксной и постфиксной формой записи счетчика цикла   Разница между префиксной и постфиксной формой записи счетчика цикла  

0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
19.08.2014, 20:05 29
Но, в то же время:
Миниатюры
Разница между префиксной и постфиксной формой записи счетчика цикла  
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
19.08.2014, 20:15 30
Так что "по стандарту" не получится Там даже внутри циклов оба варианта используются.
Видать, в комитете по стандартизации С++ тоже любители потроллить сидят

Выход, видимо, один - разобраться с пониманием того, что использовать и как, а не слепо копировать стандарт или авторитетов.
0
4817 / 2278 / 287
Регистрация: 01.03.2013
Сообщений: 5,947
Записей в блоге: 28
19.08.2014, 21:08 31
Вот ведь вопрос серьезный, как у остроконечников/тупоконечников Свифта. Если смотреть с точки зрения ассемблерного листинга, то вроде как одна бабка говорит, что префиксная эффективнее. А если забыть про эти копейки и смотреть с точки зрения стройности кода, то разработчики С (а не С++, кстати) вполне правильно сделали, придумав оба варианта, и в примерах кода применяют тот, который нагляднее отражает суть задачи - в последнем скрине пример заполнения массива по индексу, ну коряво бы выглядело начинать с -1 и делать предынкремент, гораздо стройнее смотрится начинать индекс с нуля и делать постинкремент.
ЗЫ а если счетчик еще и беззнаковый, то при предынкременте начинать надо вообще с 255 если он восьмибитный и с других чисел, если другой размер типа. И зачем с этим корячиться, если есть постинкремент?
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
19.08.2014, 21:11 32
А какое отношение цикл имеет к стартовому индексу? Этот блок в любом случае выполняется после тела.
0
4817 / 2278 / 287
Регистрация: 01.03.2013
Сообщений: 5,947
Записей в блоге: 28
19.08.2014, 21:15 33
Если это так, тогда это я лохЪ, поскольку не применяю предынкремент по причине моего незнания и вытекающей из него неуверенности Тогда надо вышенаписанное мной считать бредом, а мне учить предынкремент ))))
0
John Prick
19.08.2014, 22:11
  #34

Не по теме:

Цитата Сообщение от _Ivana Посмотреть сообщение
вышенаписанное мной считать бредом, а мне учить предынкремент
Первое верное, второе - спорно, так как учить надо цикл for. :)

0
Jupiter
19.08.2014, 22:23
  #35

Не по теме:

Цитата Сообщение от _Ivana Посмотреть сообщение
ну коряво бы выглядело начинать с -1 и делать предынкремент, гораздо стройнее смотрится начинать индекс с нуля и делать постинкремент.
ЗЫ а если счетчик еще и беззнаковый, то при предынкременте начинать надо вообще с 255 если он восьмибитный и с других чисел, если другой размер типа. И зачем с этим корячиться, если есть постинкремент?
0xFF же, а то и ~0:D

0
0 / 0 / 0
Регистрация: 18.01.2015
Сообщений: 4
27.06.2015, 04:50 36
C++
1
2
3
4
5
6
7
8
  int i1 = 0;
     int i2 = 0;
    
    i2 = ++i1;
           cout << "i1= " << i1 << "  i2= " << i2 << endl;   
    
    i2 = i1++;
        cout << "i1= " << i1 << "  i2= " << i2 << endl;
Получим.
i1= 1 i2= 1

i1= 2 i2= 1
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
27.06.2015, 07:38 37
Вопрос внимательнее прочти и обрати внимание на дату...
А насчет
Цитата Сообщение от gru74ik Посмотреть сообщение
Так что "по стандарту" не получится Там даже внутри циклов оба варианта используются.
Скотт Мейерс (More Effective c++) писал
The prefix version is always preferred over the postfix in regards to objects, especially in regards to iterators.
Префиксная версия всегда предпочтительнее чем постфиксная в отношении объектов, особенно в отношении итераторов
По стандарту вообще мало что получится, если все уже не знать. Они разбросали важные кусочки по очень разным местам.
0
0 / 0 / 0
Регистрация: 21.02.2016
Сообщений: 2
24.02.2016, 23:15 38
опоздал)
0
Вездепух
Эксперт CЭксперт С++
11696 / 6375 / 1724
Регистрация: 18.10.2014
Сообщений: 16,077
25.02.2016, 03:27 39
Во-первых, у префиксного и постфиксного инкремента разная семантика результата. Первый возвращает новое значение (как lvalue), второй - старое значение (как rvalue). Поэтому в реальном коде следует выбирать именно тот вариант, который возвращает именно нужный вам результат. Это - главный критерий выбора между префиксным и постфиксным вариантами.

В-вторых, когда возвращаемое значение оператора роли не играет вообще (игнорируется), как в вышеприведенном примере с 'for', предпочтительнее применять именно префиксный вариант. В общем случае, префиксный вариант эффективнее, ибо он не требует создания копии объекта с сохраненным старым значением. Именно так, через создание копии со старым значением в общем случае реализуется постфиксный инкремент. Особо умный компилятор может уметь оптимизировать код постфиксного инкремента в ситуациях, когда результат оператора игнорируется, тем самым устраняя разницу в производительности. Но полагаться на это не стоит.

В-третьих, вышесказанные соображения эффективности применимы в первую очередь к относительно "тяжелым" пользовательским типам, и не играют роли при работе с фундаментальными типами, такими как 'int'. Тем не менее, для единообразия в С++ принято придерживаться префиксного инкремента. В языке С, где инкремент применим только к фундаментальным типам, не имеет значения, какой вариант применять (разумеется, только в ситуациях, когда вы игнорируете результат оператора).

В-четвертых, никакого "как в стандарте" тут нет и быть не может. Стандарт такими вопросам не занимается.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
25.02.2016, 03:54 40
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Особо умный компилятор может уметь оптимизировать код постфиксного инкремента в ситуациях, когда результат оператора игнорируется, тем самым устраняя разницу в производительности. Но полагаться на это не стоит.
все топовые компиляторы уже давным давно
научились оптимизировать неиспользуемые значения.
0
25.02.2016, 03:54
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.02.2016, 03:54
Помогаю со студенческими работами здесь

Есть ли разница в оптимизации между определением переменной до цикла
Подскажите, есть ли разница в производительности между int i; while () { .... .... ...

Написать программу, преобразующую строку в префиксной форме в строку в постфиксной форме
Помоги пожалуйста объяснить, что и как надо сделать в моей задаче: написать программу,...

В чем разница между этими двумя способами записи?
В чем разница между этими двумя способами записи? entry = (score, name) и score, name = entry ...

построить выражение в префиксной записи
дано выражение 1+(2*(2-4/7)) построить выражение в префиксной записи


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru