Постфикс и префикс приращения оператора в цикле for

Возможный дубликат:
Разница между я ++ и ++ я в цикле?

Может кто-нибудь объяснить, в чем разница между ними:

for(unsigned col = 0; col < n; ++col, num_to_fill >>= 1U)
{

    for(unsigned row = num_to_fill; row < (1U << n); row += (num_to_fill * 2))
    {
        std::fill_n(&output[col][row], num_to_fill, 1);
    }
}

и

for(unsigned col = 0; col < n; col++, num_to_fill >>= 1U)
{

    for(unsigned row = num_to_fill; row < (1U << n); row += (num_to_fill * 2))
    {
        std::fill_n(&output[col][row], num_to_fill, 1);
    }
}

Когда col=0, In ex.1 Output[col][row] будет output[1][row], а In ex.2 Output[col][row] будет output[0][row]. Я прав?

Вопрос 2: Использует ли >>= 1U вместо /= 2 какую-либо разницу?

Ответы

Ответ 1

Это не имеет никакого значения для значения col в цикле - предполагается, что col является примитивным значением. Если col был классом, операторы префикса и постфикса "++" могут быть перегружены, чтобы сделать две разные вещи, хотя я бы счел это плохой практикой. Рассмотрим следующий пример:

#include <iostream>

using namespace std;

int main() {
    for(int i = 0; i < 10; i++) {
        cout << i << endl;
    }

    cout << endl;

    for(int i = 0; i < 10; ++i) {
        cout << i << endl;
    }

}

Оба из них просто распечатывают от 0 до 9, несмотря на то, что вы предварительно увеличиваете один, а затем увеличиваете в другом. Инкремент i происходит в конце каждого цикла цикла, независимо от того, используете ли вы до или после приращения. Я считаю, что pre-incrementing более эффективен, поскольку - и я могу ошибаться здесь - компилятору тогда не нужно использовать временную переменную 1. но это было бы заметно только в том случае, если вы зацикливаете очень долго (и, конечно, 'Больше критических грехов совершается во имя эффективности, чем для любой другой отдельной причины.

Что касается вопроса 2:

Вопрос 2: Использует ли → = 1U вместо =/2 имеют значение?

Вряд ли. Бит сдвиг будет быстрее, если компилятор не оптимизировал, но, скорее всего, ваш компилятор будет оптимизировать это с небольшим сдвигом.

В качестве побочного примечания я обычно нахожу выполнение unsigned variableName (т.е. отбрасывание int) плохой практики - хотя С++ будет зацикливаться на int в любом месте, которое отсутствует, оно менее читаемо для меня.

1.: Стивен в комментариях (другой Стивен;)) отмечает, что "Pre-increment более эффективен для стандартных итераторов контейнера библиотеки, но для примитивных типов он не отличается, поскольку копирование целое число дешевле, чем копирование большего итератора (в частности, std:: set и std:: map iterators).

Ответ 2

Нет разницы для unsigned. Тем не менее, для классов с перегруженным operator++ будет разница, потому что он будет вызывать различные перегрузки (обычно оператор postfix создает копию класса, что означает, что он может быть медленнее).

Использует ли → = 1U вместо /= 2 какую-либо разницу?

Наверное, нет. Его семантика одинакова для unsigned, и компиляторы обычно относятся к ним одинаково и могут менять один на другой, если он быстрее.