С Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 34, средняя оценка - 4.85
Saiberg
19 / 19 / 1
Регистрация: 23.09.2010
Сообщений: 193
#1

i++ vs ++i (циклы) - C++

11.06.2011, 15:05. Просмотров 4599. Ответов 46
Метки нет (Все метки)

Собстно стало интересно почему все пишут
C++
1
2
3
for(ptrdiff i = 0; i < 10; i++) {
 
}
постфиксный инкремент медленнее, а в данном случае в нем смысла я не вижу. для красоты что ли?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.06.2011, 15:05
Здравствуйте! Я подобрал для вас темы с ответами на вопрос i++ vs ++i (циклы) (C++):

Заменить в коде циклы for на циклы while - C++
int i, j, n; bool a; cin &gt;&gt; i &gt;&gt; n; for (i; i&lt;n; i++) { a = true; for (j = 2; j &lt;= i / 2; j++) if ((i%j) == 0) a =...

Циклы do и while - C++
Приветсвую всех. Прошу помощи в решении двух задач: 1.Составить программу для определения, является ли натуральное число k степенью...

Циклы - C++
1)Используя перебор значений найти все числа из диапазона от n до m, которые при возведении в квадрат дают палиндром 2)В соревнованиях...

Циклы - C++
Дан номер телевизионного канала(от 1 до 5). Вывести на экран наиболее популярные программы заданного канала.

циклы - C++
вывести на экран все целые числа из диапазона от А до Б, кратные трем (А&lt;=B)

циклы - C++
помогите вывести таблицу 4 3 2 1 0 3 2 1 0 2 1 0 1 0 0

46
fasked
Эксперт С++
4951 / 2531 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
12.09.2011, 17:39 #31
C++
1
2
3
int v=0;
for (int i=0; i<INT_MAX/2; )
* * * * * * * * v=++i;
Да любой вменяемый компилятор оба цикла должен преобразовать в... о чем речь вообще
C++
1
int v = INT_MAX/2;
0
OstapBender
584 / 523 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
12.09.2011, 18:49 #32
видимо gcc и VS 2010 невменяемые
0
fasked
Эксперт С++
4951 / 2531 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
12.09.2011, 18:49 #33
OstapBender, попробуйте поставить уровень оптимизации повыше.
0
OstapBender
584 / 523 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
12.09.2011, 20:37 #34
да уж выдаёт меньше 1 сотой секунды. хы-хы оптимизация скорости решает конечно.
0
desp
14 / 14 / 0
Регистрация: 17.10.2009
Сообщений: 58
12.09.2011, 20:53 #35
Цитата Сообщение от OstapBender Посмотреть сообщение
да уж выдаёт меньше 1 сотой секунды. хы-хы оптимизация скорости решает конечно.
для высоконагруженного вебсервиса совсем неплохо.
я к тому, что все относительно и гыгыкать над тем, что сэкономилась сотая секунды просто глупо.
0
fasked
Эксперт С++
4951 / 2531 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
12.09.2011, 21:30 #36
Цитата Сообщение от desp Посмотреть сообщение
для высоконагруженного вебсервиса совсем неплохо.
я к тому, что все относительно и гыгыкать над тем, что сэкономилась сотая секунды просто глупо.
Я думаю, что господин OstapBender вовсе не хы-хыкал, потому что результаты следующие:
C
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <limits.h>
 
int main() {
    int v, i;
    for (i = 0; i < INT_MAX/2; )
        v = ++i;
 
    printf("%d\n", v);
}
Код
fasked@k50id:~$ gcc opt.c -oopt
fasked@k50id:~$ time ./opt 
1073741823

real	0m3.916s
user	0m3.900s
sys	0m0.000s
fasked@k50id:~$ gcc opt.c -oopt -O2
fasked@k50id:~$ time ./opt 
1073741823

real	0m0.002s
user	0m0.000s
sys	0m0.000s
fasked@k50id:~$
То есть цикл на самом деле выпиливается при оптимизации. В какой-то похожей теме я даже приводил генерируемый ассемблерный листинг в доказательство.
0
desp
14 / 14 / 0
Регистрация: 17.10.2009
Сообщений: 58
12.09.2011, 21:32 #37
мой косяк. посыпаю голову пеплом
0
kazak
3050 / 2371 / 160
Регистрация: 11.03.2009
Сообщений: 5,436
Завершенные тесты: 1
12.09.2011, 23:52 #38
Цитата Сообщение от silent_1991 Посмотреть сообщение
поскольку при постинкременте всё равно создаётся временный объект
Для встроенных типов нет.

Цитата Сообщение от fasked Посмотреть сообщение
Да любой вменяемый компилятор оба цикла должен преобразовать
Эмм... поскольку переменная v нигде не используется, то любой вменяемый компилятор при оптимизации должен выкинуть ее нафиг, вместе с циклом.
1
fasked
Эксперт С++
4951 / 2531 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
13.09.2011, 07:35 #39
Цитата Сообщение от kazak Посмотреть сообщение
поскольку переменная v нигде не используется, то любой вменяемый компилятор при оптимизации должен выкинуть ее нафиг, вместе с циклом
Ваша правда
0
Evg
Эксперт CАвтор FAQ
18377 / 6424 / 441
Регистрация: 30.03.2009
Сообщений: 17,832
Записей в блоге: 28
13.09.2011, 18:27 #40
Для префиксной и постфиксной записи "i++", висящей в воздухе (что мы на блюдаем в цикле for) разницы нет никакой.

Когда эта запись используется в выражениях, то разница есть. Причём разница в семантике исполнения, что, формально делает незаконным сравнения по типу того, что сделаны в посте #9 - коды формально неэквивалентны. Но если всё-таки сравнить, то

C
1
a=b++;
эквивалентно
C
1
a=b;b=b+1;
что может исполниться в параллель на двух исполняющих устройствах (все нормальные современные процессоры имеют несколько конвейеров)

C
1
a=++b;
эквивалентно
C
1
b=b+1;a=b;
что на первый взгляд параллельно не может исполняться, потому как второй оператор зависит от первого. Но любой компилятор преобразует это в
C
1
b=b+1;a=b+1;
что успешно исполнится в параллель

Поэтому разницы в скорости исполнения по сути дела нет.

Разумеется, тут речь не идёт о переопределённых операторах Си++, хотя бы потому, что префиксный и потфиксный операторы могут вообще разные вещи выполнять

Добавлено через 32 секунды
Да. Любое сравнение на проивзодительность всегда должно проводиться в режиме с оптимизациями
1
Сыроежка
Заблокирован
13.09.2011, 18:36 #41
Цитата Сообщение от Saiberg Посмотреть сообщение
Собстно стало интересно почему все пишут
C++
1
2
3
for(ptrdiff i = 0; i < 10; i++) {
 
}
постфиксный инкремент медленнее, а в данном случае в нем смысла я не вижу. для красоты что ли?
В данном контексте постфиксный инкремент не является медленнее, Так что ваш вопрос не состоятелен.
Но даже если и есть какое-нибудь преимущество в скорости, тем не мене во многих стандартных алгоритмах вы найдете использование таких конструкций, как

C++
1
*iterator++
вместо двух выражений

C++
1
*iterator; ++iterator;
То есть читабельность кода и простота его восприятия значительно перевешивают данную мышиную возню с, якобы, оптимизацией.
0
Блудадей
59 / 6 / 1
Регистрация: 09.09.2011
Сообщений: 12
14.09.2011, 10:28 #42
Решил протестировать с функцией GetThreadTimes(VS C++ 2010)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <windows.h>
#include <iostream>
 
using namespace std;
 
_int64 FileTimeToQuadWord(PFILETIME ptt) 
{ 
return(Int64ShllMod32(ptt->dwHighDateTime, 32) | ptt->dwLowDateTime); 
} 
 
int main(){
volatile int v=0;
 
 
FILETIME ftUserStart, ftKernalStart, ftBuff,
         ftUserEnd  , ftKernalEnd;
 
HANDLE hThread = GetCurrentThread();
 
//------------------------------------------------------------------------------------
 
GetThreadTimes(hThread,&ftBuff,&ftBuff,&ftKernalStart,&ftUserStart);
 
for (int i=0; i<INT_MAX/2; ++i )
      v=i;
 
 
GetThreadTimes(hThread,&ftBuff,&ftBuff,&ftKernalEnd,&ftUserEnd);
 
cout<<v<<endl;//что бы оптимизатор не удалил циклы
 
 
cout<<"++i User "<<FileTimeToQuadWord(&ftUserEnd)-FileTimeToQuadWord(&ftUserStart)<<endl;
cout<<"++i Kernal "<<FileTimeToQuadWord(&ftKernalEnd)-FileTimeToQuadWord(&ftKernalStart)<<endl;
 
//----------------------------------------------------------------------------------
 
GetThreadTimes(hThread,&ftBuff,&ftBuff,&ftKernalStart,&ftUserStart);
 
for (int i=0; i<INT_MAX/2; i++ )
      v=i;
 
GetThreadTimes(hThread,&ftBuff,&ftBuff,&ftKernalEnd,&ftUserEnd);
 
cout<<v<<endl;
 
cout<<"i++ User "<<FileTimeToQuadWord(&ftUserEnd)-FileTimeToQuadWord(&ftUserStart)<<endl;
cout<<"i++ Kernal "<<FileTimeToQuadWord(&ftKernalEnd)-FileTimeToQuadWord(&ftKernalStart)<<endl;
 
cin.get();
 
return 0;
}
Результаты:
Код
Без оптимизации:
++i User 36250000
++i Kernal 0

i++ User 35625000
i++ Kernal 0

"Максимальная скорость":
++i User 12968750
++i Kernal 0

i++ User 12656250
i++ Kernal 0

"Полная оптимизация":
++i User 12812500
++i Kernal 0

i++ User 12343750
i++ Kernal 0
Добавлено через 25 минут
Сейчас протестировал на C++Builder 2009 результат обратный, так что зависит от среды
0
Evg
Эксперт CАвтор FAQ
18377 / 6424 / 441
Регистрация: 30.03.2009
Сообщений: 17,832
Записей в блоге: 28
14.09.2011, 11:57 #43
Цитата Сообщение от Блудадей Посмотреть сообщение
так что зависит от среды
Это бред полный. Посмотри ассемблерные коды в обоих случаях и попробуй найти отличия. Разница во времени исполнения - порядка 5%, что является скорее флуктуацией, чем различием. Я не знаю, в каких попугаях там оно измеряется, но для нормального сравнения на скорость нужны времена не меньше десятков или сотен секунд. Более того, для честного измерения нужно сравнивать два бинарника, а не два фрагмента в одном бинарнике, потому как во втором случае уже начинает играть роль такие эффекты, как положение кода в памяти, которое влияет на работу кэша. Ещё не дай боже оно на границе страницы оказалось или в разных страницах памяти. И куча подобных тонкостей

Добавлено через 27 минут
К тому же на фоне работы цикла операция инкрементации занимает мизерную долю времени, что ещё сильнее загрубляет точность измерения
1
TheAthlete
153 / 153 / 13
Регистрация: 31.08.2010
Сообщений: 536
14.09.2011, 14:20 #44
на хабре есть статья по этому поводу, для общего развития советую почитать: Есть ли практический смысл использовать для итераторов префиксный оператор инкремента ++it, вместо постфиксного it++
0
Evg
Эксперт CАвтор FAQ
18377 / 6424 / 441
Регистрация: 30.03.2009
Сообщений: 17,832
Записей в блоге: 28
14.09.2011, 15:11 #45
Цитата Сообщение от TheAthlete Посмотреть сообщение
Про итераторы уже всё напислаи в начале данной темы. А экономия на спичках в отладочном режиме при помощи префиксной записи - очередная ерунда. Если человеку нравится писать так, а не эдак - ради бога. Но считать при этом, что вот по таким крупицам можно наскрести 20% в скорости работы - чистый бред. Такие проценты достигаются только за счёт правильного проектирования программы, правильной реализации алгоритмов и т.п., а не за счёт экономии на спичках. Но в целом автор молодец: задумался над вопросом, разобрался в нём, рассказал людям в доходчивой форме и с нормально подведённым итогом
0
14.09.2011, 15:11
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.09.2011, 15:11
Привет! Вот еще темы с ответами:

циклы - C++
с точностью е=0.001

Циклы в Cи - C++
Всем привет, в общим столкнулся с проблемой, мне необходимо пробежаться по одной и той же строчке содержащею цифры например 1,2,3,4,5... ...

Циклы - C++
Как написать программу, в которой нужно сложить значения получаемые в цикле? z=sin(\sum_{3}^{10}(a*k+c)) a,c известны

Циклы - C++
Добрый день! Хочу попросить помощи в решении следующей задачи: Условие 1: Напишите программу, рассчитывающую сумму денег, которую вы...


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

Или воспользуйтесь поиском по форуму:
45
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.