Ответ
Разница заключается в значении, которое возвращает оператор, и в потенциальной эффективности.
Семантика
- Преинкремент (
++i): "Увеличить, затем использовать".- Значение
iувеличивается на 1. - Возвращается ссылка на уже изменённый объект
i.
- Значение
- Постинкремент (
i++): "Использовать, затем увеличить".- Сохраняется копия исходного значения
i. - Значение
iувеличивается на 1. - Возвращается сохранённая копия (старое значение).
- Сохраняется копия исходного значения
Наглядный пример с встроенными типами:
int i = 5;
int a = ++i; // Шаг 1: i = 6. Шаг 2: a = i (т.е. 6).
// Результат: i == 6, a == 6
int j = 5;
int b = j++; // Шаг 1: сохранить старое j (5). Шаг 2: j = 6. Шаг 3: b = старое значение (5).
// Результат: j == 6, b == 5
Вопрос эффективности (для пользовательских типов)
Для встроенных типов (int, char) современные компиляторы генерируют идентичный оптимизированный код, и разницы в скорости нет.
Однако для типов с перегруженными операторами (например, итераторы) ++i обычно предпочтительнее:
class MyIterator {
// Преинкремент: работает с текущим объектом, возвращает ссылку.
MyIterator& operator++() {
// ... логика инкремента ...
return *this;
}
// Постинкремент: должен создать копию ДО изменения, вернуть её.
MyIterator operator++(int) { // int — фиктивный параметр для отличия сигнатур
MyIterator temp = *this; // ВОТ ОНА, ДОПОЛНИТЕЛЬНАЯ КОПИЯ!
++(*this); // Используем уже реализованный преинкремент
return temp; // Возвращаем старую копию
}
};
Создание временного объекта в operator++(int) может быть накладным для сложных типов.
Рекомендация (best practice):
- В циклах
forвсегда используйте++i. Это привычка, которая гарантирует максимальную эффективность для любых типов.for (auto it = vec.begin(); it != vec.end(); ++it) { // Хорошо // for (...; ...; it++) { // Менее оптимально для не-POD типов - Используйте
i++только тогда, когда вам действительно нужно старое значение в выражении.auto old_value = counter++; // Логично: сохраняем старое значение, счётчик растёт. process(ptr++); // Обработать текущий элемент, затем сдвинуть указатель.