В настоящее время я изучаю C ++ и некоторое время назад узнал об увеличении. Я знаю, что вы можете использовать «++ x» для увеличения до и «x ++», чтобы сделать это после.
Тем не менее, я действительно не знаю, когда использовать любой из двух ... Я никогда не использовал "++ x", и до сих пор все работало нормально - так когда мне его использовать?
Пример: когда в цикле for предпочтительнее использовать «++ x»?
Кроме того, может ли кто-нибудь точно объяснить, как работают разные приращения (или убывания)? Я был бы очень признателен.
источник
x++
это rvalue со значениемx
до приращения,x++
это lvalue со значениемx
после приращения. Ни одно из выражений не гарантирует, что фактическое увеличенное значение сохраняется обратно в x, гарантируется только то, что это произойдет до следующей точки последовательности. «после обработки текущего оператора» не является строго точным, поскольку некоторые выражения имеют точки последовательности, а некоторые операторы являются составными операторами.Скотт Мейерс советует вам отдавать предпочтение префиксу, за исключением тех случаев, когда логика подсказывает, что постфикс уместен.
Пункт №6 «Более эффективный C ++» - это для меня достаточный авторитет.
Для тех, кто не владеет книгой, вот уместные цитаты. Со страницы 32:
И на странице 34:
источник
i++
или++i
, сгенерированный код тот же.++x
и наx++
самом деле имеет значение, это гораздо более важно , что вы на самом деле использовать компилятор , который не может полностью и правильно оптимизировать либо версии независимо от того, что в контекст. «Поскольку я использую этот хреновый старый молоток, я могу забивать гвозди только под углом 43,7 градуса» - плохой аргумент в пользу строительства дома, забивая гвозди только под углом 43,7 градуса. Используйте лучший инструмент.Из cppreference при увеличении итераторов:
Iter operator++(int) { Iter tmp(*this); // store the old value in a temporary object ++*this; // call pre-increment return tmp; // return the old value }
Предварительное приращение не создает временный объект. Это может иметь большое значение, если создание вашего объекта дорогое.
источник
Я просто хочу заметить, что сгенерированный код будет таким же, если вы используете пре / пост приращение, когда семантика (до / после) не имеет значения.
пример:
pre.cpp:
#include <iostream> int main() { int i = 13; i++; for (; i < 42; i++) { std::cout << i << std::endl; } }
post.cpp:
#include <iostream> int main() { int i = 13; ++i; for (; i < 42; ++i) { std::cout << i << std::endl; } }
_
$> g++ -S pre.cpp $> g++ -S post.cpp $> diff pre.s post.s 1c1 < .file "pre.cpp" --- > .file "post.cpp"
источник
std::map::iterator
? Конечно, там два оператора разные, но мне любопытно, будет ли компилятор оптимизировать постфиксный префикс, если результат не используется. Я не думаю, что это разрешено - учитывая, что версия postfix может содержать побочные эффекты.Самая важная вещь, о которой следует помнить, imo, заключается в том, что x ++ должен возвращать значение до того, как фактически произошло приращение, поэтому он должен сделать временную копию объекта (до приращения). Это менее эффективно, чем ++ x, который увеличивается на месте и возвращается.
Однако стоит упомянуть еще одну вещь: большинство компиляторов смогут оптимизировать такие ненужные вещи, когда это возможно, например, оба варианта приведут к одному и тому же коду здесь:
for (int i(0);i<10;++i) for (int i(0);i<10;i++)
источник
Я согласен с @BeowulfOF, хотя для ясности я всегда выступал бы за разделение заявлений, чтобы логика была абсолютно ясной, то есть:
или
Итак, мой ответ: если вы пишете четкий код, это редко имеет значение (а если это имеет значение, ваш код, вероятно, недостаточно ясен).
источник
Просто хотел еще раз подчеркнуть, что ожидается, что ++ x будет быстрее, чем x ++ (особенно, если x является объектом некоторого произвольного типа), поэтому, если это не требуется по логическим причинам, следует использовать ++ x.
источник
Вы правильно объяснили разницу. Это просто зависит от того, хотите ли вы, чтобы x увеличивался перед каждым запуском цикла или после этого. Что подходит, зависит от логики вашей программы.
Важное различие при работе с итераторами STL (которые также реализуют эти операторы) заключается в том, что он ++ создает копию объекта, на который указывает итератор, затем увеличивает его и затем возвращает копию. ++ он, с другой стороны, сначала выполняет приращение, а затем возвращает ссылку на объект, на который теперь указывает итератор. Это в основном актуально, когда важен каждый бит производительности или когда вы реализуете свой собственный STL-итератор.
Изменить: исправлено смешение префикса и суффикса.
источник
Пример 1:
Когда несколько значений каскадированы с << с использованием cout, тогда вычисления (если есть) выполняются справа налево, но печать выполняется слева направо, например (если val, если изначально 10)
cout<< ++val<<" "<< val++<<" "<< val;
приведет к
12 10 10
Пример 2:
В Turbo C ++, если в выражении обнаружено несколько вхождений ++ или (в любой форме), то сначала вычисляются все префиксные формы, затем вычисляется выражение и, наконец, вычисляются постфиксные формы, например,
int a=10,b; b=a++ + ++a + ++a + a; cout<<b<<a<<endl;
Его вывод в Turbo C ++ будет
48 13
В то время как в современном компиляторе он будет выводиться (потому что они строго следуют правилам)
45 13
выражений варьируются от компилятора к компилятору.
источник
Понимание синтаксиса языка важно при рассмотрении ясности кода. Рассмотрите возможность копирования символьной строки, например, с постинкрементом:
char a[256] = "Hello world!"; char b[256]; int i = 0; do { b[i] = a[i]; } while (a[i++]);
Мы хотим, чтобы цикл выполнялся, встречая нулевой символ (который проверяет ложь) в конце строки. Это требует проверки предварительного приращения значения, а также увеличения индекса. Но не обязательно в таком порядке - способ закодировать это с предварительным приращением:
int i = -1; do { ++i; b[i] = a[i]; } while (a[i]);
Это вопрос вкуса, который яснее, и если на машине есть несколько регистров, оба должны иметь одинаковое время выполнения, даже если a [i] - функция, которая является дорогой или имеет побочные эффекты. Существенная разница может заключаться в выходном значении индекса.
источник