Почему эта реализация:
T& T::operator+=( const T& ) {
// ... implementation ...
return *this;
}
T operator+( const T& lhs, const T& rhs ) {
T temp( lhs );
return temp += rhs;
}
распространяются чаще, чем этот:
T& T::operator+=( const T& rhs ) {
*this = *this + rhs;
return *this;
}
T operator+( const T& lhs, const T& rhs ) {
// ... implementation ...
return some_result;
}
Есть ли какая-то причина, или это просто случайное совпадение, что я видел, как люди применяют это несколько раз в литературе, которую я читаю, и никогда наоборот?
operator+
должен создать новый объект для хранения результата. operator+=
не нужен новый объект.
Если ты пишешь operator+=
с точки зрения operator+
и вы платите за создание нового объекта, назначение (или обмен) и уничтожение, и все это вам не нужно.
Кроме того, на многих процессорах аппаратное обеспечение имеет прямую поддержку +=
и аналогичные операции, где результат сохраняется обратно в один из входных регистров, и ни один для сохранения в третий регистр (например, +
).
Кстати, в вашем (оригинальном, теперь отредактированном) коде есть ошибка, которая скрывает часть дополнительной работы. Вам действительно нужно:
T& T::operator+=( const T& rhs )
{
*this = *this + rhs; // creation of temporary, move assignment, and destruction of temporary
return *this;
}
Хуже того, ваша (снова оригинальная, теперь отредактированная) предлагаемая реализация operator+
не может вернуть новый объект должным образом, вместо этого он возвращает висячую ссылку. Это неопределенное поведение.
Для тех, кто заинтересован, первый operator+
Реализация может быть улучшена еще больше с помощью передачи по значению:
T operator+( T lhs, const T& rhs )
{
lhs += rhs;
return lhs;
}
Теперь, если левый операнд operator+
является временным, будет использован конструктор перемещения, избегая копирования. Хотя с NRVO, вероятно, нет большого преимущества в конечном коде в любом случае.
Других решений пока нет …