Разница между (++i) и (i++)



В C++ я понимаю, что (++i) должен возвращать ссылку на i, потому что требуется конкатенация операторов, но чего я не могу понять, так это:



Почему (i++) должен возвращать i по значению?



Может ли кто-нибудь уточнить.

671   8  

8 ответов:

++i может быть записано как

prefix_inc (this) {
   increase this by 1
   return this
}

Поскольку реальное i возвращается, мы можем взять ссылку на него. Однако i++ выглядит как

postfix_inc (this) {
   set old_this = copy of this
   increase this by 1
   return old_this
}

Поскольку old_this - это всего лишь локальная переменная, ссылка на нее бессмысленна после завершения i++. Поэтому логически он должен возвращать значение rvalue.

i++ возвращает значение, потому что оно возвращает старое значение i, в то время как i увеличивается на 1.

Основной реализацией этого было бы:

int i++() {
  int old = i;
  i = i + 1;
  return old;
}
Таким образом, если бы он вернул ссылку, это было бы неправильное значение... так как значение i было увеличено!

Пусть foo - некоторая функция. foo(i++) вызывает foo(i) со старым значением i и инкрементами i, отсюда необходимость построения временной копии. foo(++i) инкрементирует i, а затем вызывает foo с инкрементированным значением, поэтому для повышения производительности мы можем повторно использовать ту же переменную, не нужно иметь временную копию.

I++ Это возвращает значение i до того, как он увеличивается. Таким образом, идея заключается в том, что если вы хотите использовать i в функции, а затем увеличить значение после ее использования, вы можете сделать это за один шаг. В качестве примера, вот как я бы перегрузил этот оператор для целых чисел.

Integer Integer::operator++()
{
    Integer returnValue = *this;
    this->increment();
    return returnValue;
}

Таким образом, он увеличивает значение и затем возвращает то, что он использовал. Он также не возвращает ссылку, потому что возврат ссылки будет отличаться от того, что было первоначально передано, что приведет к разрыву каскадирование.

++i Это увеличивает значение i, а затем возвращает новое значение. Таким образом, вы можете использовать это в ситуации, когда вы хотите увеличить i, а затем использовать новое значение в своей функции.

Integer Integer::operator++(Integer i)
{
    i.increment();
    return i;
}

Таким образом, значение, которое он возвращает, является увеличенным значением i.

int i = 0;
Console.Writeline(i++); // Output 0, after that, i will be 1


int x = 0;
Console.Writeline(++x); // Output 1

Примечание: код находится в C#

В то время как префикс ++i возвращает увеличенное значение, а префикс i++ возвращает старое значение и увеличивает его впоследствии, выбор оператора важен, если вы заботитесь о циклах процессора. Приращение префикса происходит быстрее ; -)

5 центов:

Вследствие того, что i++ делает копию, она медленнее для не-POD переменных (т. е. итераторов). Вы должны использовать ++i везде, где это возможно.

Лично я всегда использую for(...;...;++i) вместо for(...;...;i++), хотя компилятор должен оптимизировать это.

Если вы когда-нибудь попадете в сценарий, где это имеет значение, вы делаете это неправильно.

Comments

    Ничего не найдено.