Что касается for(), зачем использовать я ++, а не ++ i?

Возможно, это не имеет значения для компилятора после его оптимизации, но в C/С++ я вижу, что большинство людей делают цикл for в виде:

for (i = 0; i < arr.length; i++)

где приращение выполняется с помощью post fix ++. Я получаю разницу между двумя формами. я ++ возвращает текущее значение i, но затем добавляет 1 к я в тишине. ++ я сначала добавляет 1 к я и возвращает новое значение (будучи еще 1 больше, чем я).

Я думаю, что я ++ требует немного больше работы, поскольку предыдущее значение нужно сохранить в дополнение к следующему значению: Push * (& i) для стека (или загрузки для регистрации); increment * (& i). Versus ++ i: Increment * (& i); затем используйте * (& i) по мере необходимости.

(я понимаю, что операция "Increment * (& i)" может включать в себя нагрузку регистра, в зависимости от дизайна ЦП. В этом случае я ++ потребуется либо другой регистр, либо push файл.)

В любом случае, в какой момент и почему, я ++ стал более модным?


Я склонен поверить ажеглову: это педагогическая вещь, и поскольку большинство из нас делает C/С++ в системе Window или * nix, где компиляторы имеют высокое качество, никто не пострадал.

Если вы используете компилятор низкого качества или интерпретируемую среду, вам может потребоваться быть чувствительным к этому. Конечно, если вы делаете продвинутый С++ или драйвер устройства или встроенную работу, мы надеемся, что вы достаточно опытные, чтобы это было неважно. (У собак есть природа Будды? Кто действительно должен знать?)

Ответ 1

Моя теория (почему я ++ более модно) заключается в том, что, когда люди учатся C (или С++), они в конечном итоге учатся кодировать итерации следующим образом:

while( *p++ ) {
    ...
}

Обратите внимание, что здесь важна форма постфиксирования (использование формы инфикса создало бы одноразовый тип ошибки).

Когда придет время написать цикл for, где ++i или i++ не имеет большого значения, более естественно использовать постфиксную форму.

ADDED: То, что я написал выше, действительно относится к примитивным типам. Когда вы кодируете что-то с примитивными типами, вы, как правило, делаете что-то быстро и делаете то, что приходит естественно. Это важное предостережение, которое мне нужно приложить к моей теории.

Если ++ является перегруженным оператором в классе С++ (возможность, предложенная Rich K. в комментариях), вам, конечно же, нужно с особой осторожностью кодировать циклы с участием таких классов, а не делать простые вещи, которые приходят естественным образом.

Ответ 2

Неважно, что вы используете. На некоторых крайне устаревших машинах, а в некоторых случаях на С++, ++i более эффективен, но современные компиляторы не сохраняют результат, если он не хранится. Что касается того, когда стало популярным postincriment в циклах for, моя копия второго выпуска K & R использует i++ на стр. 65 (первый цикл for, который я обнаружил, когда просматривал.)

Ответ 3

По какой-то причине i++ стал более идиоматичным в C, хотя он создает ненужную копию. (Я думал, что это было через K & R, но я вижу, что это обсуждается в других ответах.) Но я не думаю, что есть разница в производительности в C, где он используется только для встроенных модулей, для которых компилятор может оптимизируйте операцию копирования.

Это действительно имеет значение в С++, однако, где i может быть определяемым пользователем типом, для которого operator++() перегружен. Компилятор, возможно, не сможет утверждать, что операция копирования не имеет видимых побочных эффектов и, следовательно, не сможет ее устранить.

Ответ 4

Что касается причины, вот что сказал K & R по этому вопросу:

Брайан Керниган

вам придется попросить Дениса (и это может быть в бумаге HOPL). у меня есть что он был связан с операцией post-increment в pdp-11, хотя помимо этого я не знаю, поэтому не цитируйте меня.

в С++ предпочтительный стиль для итераторов - это на самом деле ++ я для некоторых тонких причина реализации.

Деннис Ричи

Нет особой причины, она просто стала модной. Полученный код идентичен на PDP-11, просто инструкция inc, без автоинкремента.

Ответ 5

Для целых типов две формы должны быть эквивалентными, если вы не используете значение выражения. Это больше не верно в мире С++ с более сложными типами, но сохраняется в имени языка.

Я подозреваю, что "i ++" стал более популярным в первые дни, потому что стиль, используемый в оригинальной книге K & R "C Programming Language". Вы должны спросить их, почему они выбрали этот вариант.

Ответ 6

Потому что, как только вы начнете использовать "++ i", люди будут смущены и любопытны. Они будут останавливать там повседневную работу и начинать поиски для объяснений. Через 12 минут они перейдут в переполнение стека и зададут такой вопрос. И вуаля, ваш работодатель просто потратил еще $10

Ответ 7

Возвращаясь немного дальше, чем K & R, я посмотрел на своего предшественника: учебник Kernighan C (~ 1975). Здесь первые несколько примеров while используют ++n. Но каждый цикл for использует i++. Поэтому, чтобы ответить на ваш вопрос: почти с самого начала i++ стало более модным.

Ответ 8

Мне кажется, что это стало более модным с созданием С++, поскольку С++ позволяет вам вызывать ++ на нетривиальных объектах.

Хорошо, я уточняю: если вы вызываете i++ и i - нетривиальный объект, то сохранение копии, содержащей значение я до инкремента, будет дороже, чем, например, указатель или целое число.

Ответ 9

На некотором уровне это идиоматический код C. Это как раз то, как обычно делаются. Если это ваше узкое место в производительности, вы, вероятно, работаете над уникальной проблемой.

Однако, глядя на мой K & R Язык программирования C, 1-е издание, первый экземпляр, который я нахожу для я в цикле (стр. 38), действительно использует ++ i, а не я ++.

Ответ 10

Я думаю, что мои предшественники правы в отношении побочных эффектов выбора постинкремента по сравнению с преинкрементами.

Для его fashonability это может быть так же просто, как вы начинаете все три выражения внутри оператора for одним и тем же повторяющимся способом, к чему, по-видимому, стремится человеческий мозг.

Ответ 11

Я бы добавил, что другие люди сказали вам, что основное правило: быть последовательным. Выберите один и не используйте другой, если это не конкретный случай.

Ответ 12

Если цикл слишком длинный, вам нужно перезагрузить значение в кеше, чтобы увеличить его до перехода к началу. То, что вам не нужно c++ i, не перемещается в кеш.

Ответ 13

В C все операторы, которые приводят к переменной, имеющей новое значение, кроме префикса inc/dec, изменяют переменную слева (i = 2, я + = 5 и т.д.). Поэтому в ситуациях, когда ++ я и я ++ могут быть взаимозаменяемы, многие люди более удобны с я ++, потому что оператор находится справа, изменяя переменную слева

Скажите, пожалуйста, если это первое предложение неверно, я не эксперт с C.