2008-09-23 6 views
1

Я предположил, что каноническая форма для оператора +, предполагая существование перегруженного оператора + = функции члена, было так:Какая лучшая подпись для перегруженных арифметических операторов в C++?

const T operator+(const T& lhs, const T& rhs) 
{ 
    return T(lhs) +=rhs; 
} 

Но это было указано мне, что это будет работать:

const T operator+ (T lhs, const T& rhs) 
{ 
    return lhs+=rhs; 
} 

По существу, эта форма передает создание временного из тела реализации в вызов функции.

Кажется немного неудобным иметь разные типы для двух параметров, но есть ли что-то неправильное со второй формой? Есть ли причина предпочитать одну над другой?

ответ

2

С отредактированным вопросом предпочтительной будет первая форма. Компилятор скорее оптимизирует возвращаемое значение (это можно проверить, поставив точку останова в конструкторе для T). Первая форма также принимает оба параметра как const, что было бы более желательно.

Исследования на тему оптимизации стоимости возврата, например, в этой ссылке, как быстрый пример: http://www.cs.cmu.edu/~gilpin/c++/performance.html

+0

Так же делает вторую форму. – 2008-09-23 01:42:13

+0

Не обязательно. Большинство современных компиляторов обнаруживают, что требуется только одна копия и оптимизировать ее. – 2008-09-23 01:42:14

+0

(Вышеуказанное предназначено для @Kris, но на самом деле оно применимо и к @Corey.) – 2008-09-23 01:42:49

4

Я не уверен, если есть большая разница в сгенерированном коде либо.

Между этими двумя, я (лично) предпочитаю первую форму, так как она лучше передает намерение. Это касается как повторного использования оператора + =, так и идиомы прохождения templatized типов по const &.

2

Я бы предпочел первую форму для удобочитаемости.

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

1
const T operator+(const T& lhs, const T& rhs) 
{ 
    return T(lhs)+=rhs; 
} 

Почему бы вам не это, если вы хотите обрезанности?

1

Моя первая мысль заключается в том, что вторая версия может быть бесконечно более быстрой, чем первая, потому что никакая ссылка не помещается в стек в качестве аргумента. Однако это было бы очень зависимым от компилятора и зависящим, например, от того, выполняет ли компилятор оптимизацию именного возвращаемого значения или нет.

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

0

На самом деле второй предпочтительнее. Как указано в стандарте C++,

3.7.2/2: Автоматическая продолжительность хранения

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

То есть, поскольку ненаписанный временный объект создается с использованием конструктора копирования, компилятор не может использовать оптимизацию возвращаемого значения. Однако для второго случая допускается оптимизация неопределенного значения возвращаемого значения. Обратите внимание, что если ваш инвентарь компилятор назвал оптимизацию возвращаемого значения, лучший код

const T operator+(const T& lhs, const T& rhs) 
{ 
    T temp(lhs); 
    temp +=rhs; 
    return temp; 
} 
0

Я думаю, что если вы встраиваемыми их обоих (я бы, так как они просто экспедиторская функции, и, предположительно, + = оператор-функция() является вне очереди), вы получите почти неразличимое генерирование кода. Тем не менее, первый более канонический. Вторая версия бесполезно «мила».

 Смежные вопросы

  • Нет связанных вопросов^_^