Стандарты программирования на С++. 101 правило и рекомендация | страница 49
>a+=b
. При определении бинарных арифметических операторов одновременно предоставляйте и их присваивающие версии, причем делайте это с минимальным дублированием и максимальной эффективностью.В общем случае для некоторого бинарного оператора >@
(>+
, >-
, >*
и т.д.) вы должны также определить его присваивающую версию, так чтобы >a@=b
и >a=a@b
имели один и тот же смысл (причем первая версия может быть более эффективна). Канонический способ достижения данной цели состоит в определении >@
посредством >@=
следующим образом:
>T& T::operator@=(const T&) {
> // ... реализация ...
> return *this;
>}
>T operator@(const T& lhs, const T& rhs) {
> T temp(lhs);
> return temp @= rhs;
>}
Эти две функции работают в тандеме. Версия оператора с присваиванием выполняет всю необходимую работу и возвращает свой левый параметр. Версия без присваивания создает временную переменную из левого аргумента, и модифицирует ее с использованием формы оператора с присваиванием, после чего возвращает эту временную переменную.
Обратите внимание, что здесь >operator@
— функция-не член, так что она обладает желательным свойством возможности неявного преобразования как левого, так и правого параметра (см. рекомендацию 44). Например, если вы определите класс >String
, который имеет неявный конструктор, получающий аргумент типа >char
, то оператор >operator+(const String&, const String&)
, который не является членом класса, позволяет осуществлять операции как типа >char+String
, так и >String+char
; функция-член >String::operator+(const String&)
позволяет использовать только операцию >String+char
. Реализация, основной целью которой является эффективность, может определить ряд перегрузок оператора >operator@
, не являющихся членами класса, чтобы избежать увеличения количества временных переменных в процессе преобразований типов (см. рекомендацию 29).
Также делайте не членом функцию >operator@=
везде, где это возможно (см. рекомендацию 44). В любом случае, все операторы, не являющиеся членами, должны быть помещены в то же пространство имен, что и класс >T
, так что они будут легко доступны для вызывающих функций при отсутствии каких-либо сюрпризов со стороны поиска имен (см. рекомендацию 57).
Как вариант можно предусмотреть оператор >operator@
, принимающий первый параметр по значению. Таким образом вы обеспечите неявное копирование компилятором, что обеспечит ему большую свободу действий по оптимизации: