LINUX.ORG.RU

[c++] преинкремент/постинкремент

 


0

0

тут копался в CodingStyle для Qt Creator, наткнулся на интересное требование к коду.

Prefer preincrement to postincrement whenever possible.

Preincrement has potential of being faster than postincrement. Just think about the obvious implementations of pre/post-increment. This rule applies to decrement too.

++T;
--U;

T++; // not used in Qt Creator
U--; // not used in Qt Creator

а что правда преинкремент быстрее, чем постинкремент? я думал разницы нет

Ну сам подумай: при преинкременте тебе надо увеличить значение переменной и его же вернуть, а при постинкременте надо вернуть старое, но увеличить.
А вообще, вроде бы уже все компиляторы научились i++ в случаях, когда значение не используется, заменять на ++i.

gaa ★★
()

Разница может быть:

struct SomeComplexIterator {
    char mVeryImportantData[1048576];
    int mYetAnotherImportantData;

    // конструкторы деструкторы и т.п. пропускаем

    // преинкремент
    SomeComplexIterator& operator ++() {
        // манипулируем с mVeryImportantData
        ++mYetAnotherImportantData;
        return *this;
    }

    // постинкремент
    SomeComplexIterator operator ++(int) {
        SomeComplexIterator temporaryObject = *this;
        // манипулируем с mVeryImportantData
        ++mYetAnotherImportantData;
        return temporaryObject;
    }
};

nozh
()

Да, т.к. для постинкремента приходится сохранять значение перед изменением переменной, чтобы вернуть его (старое значение) после изменения переменной. А преинкремент возвращает новое значение.

Deleted
()
Ответ на: комментарий от gaa

>> А вообще, вроде бы уже все компиляторы научились i++ в случаях, когда значение не используется, заменять на ++i.

i может быть и более сложного типа, нежели int, тогда не всё так просто.

Deleted
()

я слышал такое объяснение: преинкремент компилится в 

взять X;
сделать инкремент
сохранить X;
оперировать дальше над X; 


а постинкремент в

взять X;
cохранить копию Y=X;
cделать инкремент;
сохранить инкременченный X;

оперировать дальше над Y


и отсюда очевидно что преинкремент дешевле, тк не надо возиться с двумя копиями.

c одной стороны это все лажа - компиляторы давно такое оптимизируют... 

с другой стороны - а кто помнит что с перегруженными инкрементами? их там два
(пре и пост) или оно делает копии и то что я выше описывал?

gods-little-toy ★★★
()
Ответ на: комментарий от Deleted

>i может быть и более сложного типа, нежели int, тогда не всё так просто.

недавно убедился в том, что M$-овский компилятор в вопросе оптимизации постинкремента проявляет просто-таки потрясающую наглость

jtootf ★★★★★
()
Ответ на: комментарий от z0D5e8n7x

>> короче стоит последовать рекомендации и делать везде преинкремент?

Ну если тебе не нужно старое значение, то хуже точно не будет =).

Deleted
()
Ответ на: комментарий от jtootf

>> недавно убедился в том, что M$-овский компилятор в вопросе оптимизации постинкремента проявляет просто-таки потрясающую наглость

В смысле хорошо оптимизирует или криво?

Deleted
()
Ответ на: комментарий от z0D5e8n7x

>короче стоит последовать рекомендации и делать везде преинкремент?

кроме тех случае, когда тебе нужен именно постинкремент; точно такая же рекомендация, как и по поводу ключевого слова explicit для одноаргументных конструкторов

jtootf ★★★★★
()
Ответ на: комментарий от Deleted

>В смысле хорошо оптимизирует или криво?

хорошо

jtootf ★★★★★
()
Ответ на: комментарий от gods-little-toy

>c одной стороны это все лажа - компиляторы давно такое оптимизируют...

там есть забавная фишка: по стандарту постинкремент должен вернуть копию исходного значения - т.е. объект должен буть продублирован; однако для POD-типов компиляторы весело ложат на это требование из соображений эффективности

>с другой стороны - а кто помнит что с перегруженными инкрементами? их там два (пре и пост) или оно делает копии и то что я выше описывал?

ну, должны работать по стандарту

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

> по стандарту постинкремент должен вернуть копию исходного значения - т.е. объект должен буть продублирован; однако для POD-типов компиляторы весело ложат на это требование из соображений эффективности

В смысле? Можно пример, где это проявляется?

Legioner ★★★★★
()

На самом деле цимес в том что ради исключения дублирования кода operator++(int) чуть менее чем всегда реализован через operator++() с сохранением и возвратом копии старого значения. Поэтому в постинкременте спрятано лишнее копирование и лишний вызов. Для атомарных типов разницы нет.

Absurd ★★★
()
Ответ на: комментарий от Legioner

>В смысле? Можно пример, где это проявляется?

что именно? если копирование - то любое использование стандартных итераторов. если оптимизация - то посмотреть ассемблерный листинг кода с обоими формами инкремента для int'а

jtootf ★★★★★
()

Посмотрите как реализован инкремент итератора контейнера в stl, возможно тут тот же случай.

andreyu ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.