Что я часто вижу в определениях перегрузки операторов? - PullRequest
4 голосов
/ 21 октября 2010

Например, в движке OGRE3D я часто вижу такие вещи, как

class_name class_name :: operator + (class_name & object)

Вместо

class_name class_name :: operator + (class_name object)

Ну, я не предпочитаю вторую форму, но есть ли особая причина использовать ссылку во входных данных? Имеются ли в нем особые случаи, когда необходимо использовать ссылку вместо копии по значению? Или вопрос производительности?

Ответы [ 5 ]

4 голосов
/ 21 октября 2010

Это проблема производительности.Передача по ссылке, как правило, обходится дешевле, чем передача по значению (в основном это эквивалентно передаче по указателю).

В неродственной ноте вы, вероятно, захотите, чтобы аргумент operator+ был const class_name &object.

3 голосов
/ 21 октября 2010

Рекомендуется реализовать operator+ в терминах operator+=. Сначала сделайте копию левого аргумента, затем измените его и, наконец, верните копию. Так как в любом случае вы собираетесь скопировать левый аргумент, вы можете сделать это, используя call by value для левого аргумента:

class_name operator+(class_name x, const class_name& y)
{
    return x += y;
}

В C ++ 0x вы должны включить семантику перемещения для результата:

#include <utility>

class_name operator+(class_name x, const class_name& y)
{
    return std::move(x += y);
}
2 голосов
/ 21 октября 2010

Помимо "обычных" соглашений о вызовах для обычных методов, я бы отметил, что операторы несколько своеобразны.

Основной причиной использования const& вместо передачи по значению является правильность (производительность идет на втором месте, по крайней мере, на мой взгляд). Если ваше значение может быть полиморфным, то копирование означает нарезку объектов, что в целом является неопределенным поведением.

Поэтому, если вы используете передачу по значению, вы четко указываете вызывающей стороне, что объект будет скопирован и он не должен быть полиморфным.

Другой причиной может быть производительность. Если класс маленький и его конструктор копирования тривиален, его можно было бы скопировать быстрее, чем использовать косвенное обращение (подумайте о int-like классе). В других случаях передача по значению может быть быстрее, но в не встроенных случаях они встречаются реже.

Тем не менее, я думаю, что ни одна из них не является реальной причиной, и разработчики просто выбрали это на ровном месте ...

... потому что настоящий WTF (как они говорят) заключается в том, что operator@ должен быть объявлен как свободные функции, чтобы разрешить продвижение аргумента левого аргумента ...

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

1 голос
/ 21 октября 2010

Так что object не копируется из исходного параметра. Фактически, предпочтительный способ - передать object как const и сделать operator+ как const member operator:

class_name class_name :: operator + (const class_name& object) const;
0 голосов
/ 21 октября 2010

Передача ссылки намного быстрее, чем копирование всего экземпляра вашего класса. Кроме того, если для класса не определен конструктор копирования, его может быть опасно копировать (конструктор копирования по умолчанию просто скопирует указатели, а деструктор, например, удалит их).

При передаче классов методу или оператору лучше всегда передавать ссылку. Вы можете объявить его const, чтобы быть уверенным, что он не изменен во избежание побочных эффектов.

...