28. Предпочитайте канонический вид ++ и --, и вызов префиксных операторов
28. Предпочитайте канонический вид ++ и --, и вызов префиксных операторов
Резюме
Особенность операторов инкремента и декремента состоит в том, что у них есть префиксная и постфиксная формы с немного отличающейся семантикой. Определяйте операторы operator++ и operator-- так, чтобы они подражали поведению своих встроенных двойников. Если только вам не требуется исходное значение — используйте префиксные версии операторов.
Обсуждение
Старая шутка гласит, что язык называется С++, а не ++С, потому что язык был улучшен (на что указывает инкремент), но многие продолжают использовать его как С (предыдущее значение до инкремента). К счастью, эту шутку можно считать устаревшей, но это отличная иллюстрация для понимания отличия между двумя формами операторов.
В случае ++ и -- постфиксные формы операторов возвращают исходное значение, в то время как префиксные формы возвращают новое значение. Лучше всего реализовывать постфиксный оператор с использованием префиксного. Вот канонический вид такого использования:
// ---- Префиксные операторы -----------------------
T& T::operator++() { // Префиксный вид:
// выполнение // - Выполнение
// инкремента // действий
return *this; // - return *this;
}
T& T::operator--() { // Префиксный вид:
// Выполнение // - Выполнение
// декремента // действий
return *this; // - return *this;
}
// ---- Постфиксные операторы ---------------------
T T::operator++(int) { // Постфиксный вид:
T old(*this); // - Запоминаем старое значение
++*this; // - Вызов префиксной версии
return old; // - Возврат старого значения
}
T T::operator--(int) { // Постфиксный вид:
T old(*this); // - Запоминаем старое значение
--*this; // - Вызов префиксной версии
return old; // - Возврат старого значения
}
В вызывающем коде лучше использовать префиксные операторы, если только вам не требуется исходное значение, возвращаемое постфиксной версией. Префиксная форма семантически эквивалентна, она вводится практически так же, и зачастую немного эффективнее, так как создает на один объект меньше. Это не преждевременная оптимизация, а устранение преждевременной пессимизации (см. рекомендацию 9).
Исключения
Шаблоны, используемые для научных вычислений (например, шаблоны для представления тензоров или матриц), к которым предъявляются жесткие требования по производительности. Для таких шаблонов часто приходится искать более эффективные способы реализации префиксных форм операторов.
Ссылки
[Cline99] §23.07-08 • [Dewhurst03] §87 • [Meyers96] §6 • [Stroustrup00] §19.3 • [Sutter00] §6, §20