Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.68/34: Рейтинг темы: голосов - 34, средняя оценка - 4.68
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712

Префиксный и постфиксный инкременты

16.02.2018, 11:39. Показов 6679. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую всех. Экспериментом установил, что префиксный инкремент переменной стандартного типа возвращает ссылку на эту же уже измененную переменную. Постфиксный инкремент возвращает неизмененное значение (не ссылку!).
Есть такой код:
C++
1
2
int i = 5;
i = i++ + ++i;
Данный код при компиляции дает результат 12. Написав свой класс, имитирующий тип int и перегрузив необходимые операторы, я выяснил, что операции выполняются в таком порядке: префиксный инкремент, постфиксный инкремент, сложение, присваивание.
Переменная моего класса в примере выше в конце равна 13 и это объясняется. Почему стандартная переменная равна 12 в конце?
1
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
16.02.2018, 11:39
Ответы с готовыми решениями:

Постфиксный и префиксный декремент
#include <iostream> using std::cout; int main() { int a=5; cout << (--a)-- << " "; cout << a << " "; cout << (--a)-- <<...

Префиксный и постфиксный инкремент
#include <iostream> using namespace std; int main() { int c=0; cout<<с++<<++с<<++с<<с++<<endl; return 0; ...

Как выполняется постфиксный и префиксный инкремент?
Растолкуйте! Обычно, а = с++ толкуется как а = с+1 тогда а = ++с есть а = 1+с Если использовать последнюю запись (а = 1+с),верно...

11
184 / 192 / 48
Регистрация: 25.08.2011
Сообщений: 792
16.02.2018, 11:46
код вашего класса в студию. Стандартное поведение верно а в Вашем класе сидит ошибка
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
16.02.2018, 12:19  [ТС]
C++
1
2
3
4
5
6
7
8
9
class TInt
{
 public:
 int i;
 TInt(int j) : i(j) {}
 TInt operator+(const TInt& j) const { return TInt(i + j.i); }
 TInt& operator++() { ++i; return *this; }
 TInt operator++(int) { TInt temp = *this; ++*this; return temp; }
};
0
 Аватар для COKPOWEHEU
4083 / 2681 / 432
Регистрация: 09.09.2017
Сообщений: 11,922
16.02.2018, 13:33
Цитата Сообщение от d7d1cd Посмотреть сообщение
Написав свой класс, имитирующий тип int и перегрузив необходимые операторы, я выяснил, что операции выполняются в таком порядке:
Неа, выяснили что ваша реализация выполняется в таком порядке, а что будет для исходного кода - зависит от реализации конкретного компилятора.
https://www.google.ru/search?q... kwXyir3oDQ
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
16.02.2018, 13:38  [ТС]
COKPOWEHEU, тогда объясните, почему результат разный?
0
 Аватар для COKPOWEHEU
4083 / 2681 / 432
Регистрация: 09.09.2017
Сообщений: 11,922
16.02.2018, 13:58
По ссылке все написано: компилятор может вычислять инкременты в любом порядке
i++ + ++i -> (5++) + (++5) -> 5 + 6 -> 11 (добавляем первый инкремент ->12)
i++ + ++i -> (5++) + (++i) -> 5 + (++6) -> 12
i++ + ++i -> (i++) + (++5) -> (6++) + 6 -> 12 (добавляем первый инкремент ->13)
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
16.02.2018, 14:29  [ТС]
То есть не каждый компилятор будет давать ответ 12 даже со стандартными типами данных?
0
 Аватар для COKPOWEHEU
4083 / 2681 / 432
Регистрация: 09.09.2017
Сообщений: 11,922
16.02.2018, 15:42
Рекомендую все-таки сходить по ссылке и почитать
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
16.02.2018, 15:59
Цитата Сообщение от d7d1cd Посмотреть сообщение
i = i++ + ++i;
UB.
тему можно закрывать.

для тех, кто не знает что такое UB
Кликните здесь для просмотра всего текста

в гугле забанили?
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
17.02.2018, 12:06  [ТС]
Прочитал статью по ссылке. Видимо не совсем понял, потому что в голове висит вопрос "почему в примере нет конкретики для компилятора"...
Из приоритета операций следует, что операция прединкремента имеет более низкий приоритет, чем операция постинкремента. Операция сложения имеет еще более низкий приоритет, чем указанные выше. Так же все знают, что префиксный инкремент (декремент) возвращает ссылку, постфиксный возвращает значение.

Берем выражение int i = 5; i = i++ + ++i;. Первым делом компилятор, согласно приоритетам, должен выполнить i++. Эта операция увеличит i (оно станет равно 6), но вернет не увеличенное значение (равное 5). Далее выполняется ++i. Здесь значение i (которое равно 6), увеличится (станет равно 7) и вернется ссылка на i. Следующим действием компилятор должен выполнить сложение. Он берет результат первой операции (то есть число 5) и результат второй операции (то есть ссылку на i). В итоге у операции сложения два аргумента: 5 и 7. Результат 12.

То же самое можно рассказать об int i = 5; i = ++i + ++i;. Здесь две операции прединкремента. Согласно ассоциативности эти операции должны выполняться справа налево (хотя здесь это и не имеет значения). После правого ++i в i будет лежать 6, а у операции сложения один из аргументов будет ссылка на i. После второго ++i в i будет 7, у операции сложения второй аргумент будет так же ссылка на i. Таким образом в сложении оба аргумента будут ссылками на i, в которой хранится 7. В итоге ответ 14.

Это мое видение работы компилятора. Однако, все мы знаем, что так происходит не всегда. Укажите, где я ошибаюсь в своих рассуждениях.
0
 Аватар для palva
4278 / 2970 / 693
Регистрация: 08.06.2007
Сообщений: 9,930
Записей в блоге: 5
17.02.2018, 13:13
//Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x64
Дает 13, если что. Проверить можно здесь http://rextester.com/l/cpp_online_compiler_visual

Ваши рассуждения сомнительны вот в каком отношении. Приоритет становится важным только если операции разных приоритетов стоят рядом. a*b+c*d+e*f не предполагает, что сначала выполняются умножения, а лишь то, что скобки будут расставлены так: (a*b)+(c*d)+(e*f). Третье умножение может быть выполнено после первого сложения. Также точно сложение слева направо не означает, что слагаемые будут также вычисляться слева направо а лишь то, что появятся дополнительные скобки ((a*b)+(c*d))+(e*f). Ассоциативность (плохое слово) операций означает, как будут расставлены скобки, если стоит последовательное выполнение операций одного и того же приоритета. То есть ++ ++ v означает ++ (++ v), а v ++ ++ означает (v ++) ++ Какой смысл этих выражений уже другой вопрос. Компилятор должен выдать диагностику об ошибке, если это смысла не имеет. А если операцию ++ каким-то хитрым образом перегрузить, то, возможно, смысл и появится.

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

На практике не стоит использовать подобные конструкции. Непонятно, что может произойти.
1
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
17.02.2018, 15:13
Лучший ответ Сообщение было отмечено d7d1cd как решение

Решение

http://alenacpp.blogspot.ru/20... oints.html
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
17.02.2018, 15:13
Помогаю со студенческими работами здесь

Инкремент постфиксный и префиксный - принцип работы
Hello World! Нужна ваша помощь, мозг отказывается понимать :wall:! Набрал код: #include <iostream> using namespace std; ...

Постфиксный, и префиксный экземпляры оператора приращения: в чем разница?
постфиксный, и префиксный экземпляры оператора приращения в чем разница? i++ ++i ??

Указатели: почему так происходит? Постфиксный и префиксный инкремент
В общем, вот код программы double q; for (int i(0);i<10;i++) { q=i; } cout<<q<<endl; double* d=q; ...

Поясните как работает постфиксный и префиксный оператор на примере
Здравствуйте. Здесь префиксный понятно, а что если изменить на постфиксный, как код будет работать? vector<int>::size_type...

Постфиксный и префиксный инкремент
Доброго времени суток! чем отличается ++i от i++, кто то может русским языком объяснить? Просто встал в ступор не могу понять как их работа...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru