Операторы приращения префикса / постфикса - PullRequest
21 голосов
/ 05 июля 2010

Я хочу убедиться, что правильно понимаю передачу по значению против передачи по ссылке. В частности, я смотрю префиксные / постфиксные версии оператора приращения ++ для объекта.

Предположим, у нас есть следующий класс X:

class X{
private:
    int i;
public:
 X(){i=0;}
 X& operator ++ (){ ++i; return *this; } //prefix increment

 X operator ++ (int unused){ //postfix increment
  X ret(*this);
  i++;
  return ret;
 }

 operator int(){ return i; } //int cast
};

Прежде всего, правильно ли я реализовал операторы приращения префикса / постфикса?

Во-вторых, насколько эффективен постфиксный оператор по сравнению с префиксным оператором? В частности, сколько X копий объектов создается при использовании каждой версии оператора?

Объяснение того, что именно происходит с возвратом по ссылке против возврата по значению, может помочь мне понять.


Редактировать: например, со следующим кодом ...

X a;
X b=a++;

... теперь псевдонимы a и b?

Ответы [ 3 ]

18 голосов
/ 05 июля 2010

Более идиоматично вызывать приращение префикса самого объекта в приращении постфикса:

X operator++(int)
{
    X copy(*this);
    ++*this;         // call the prefix increment
    return copy;
}

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

17 голосов
/ 05 июля 2010

Это правильная реализация.Типично, что постфиксный оператор будет ухудшать производительность, потому что вам нужно создать еще одну копию, прежде чем делать приращение (и именно поэтому я привык всегда использовать префикс, если мне не нужно что-то еще).

При возврате по ссылке вы возвращаете ссылку на l-значение для текущего объекта.Компилятор обычно реализует это, возвращая адрес текущего объекта.Это означает, что возвращать объект так же просто, как и возвращать число.

Однако при возврате по значению необходимо выполнить копирование.Это означает, что во время возврата есть больше информации для копирования (а не просто адрес), а также конструктор копирования для вызова.Вот тут-то и возникает ваша производительность.

Эффективность вашей реализации выглядит на уровне типичных реализаций.

РЕДАКТИРОВАТЬ: Что касается вашего дополнения, нет, они не являются псевдонимами.Вы создали два отдельных объекта.При возврате по значению (и при создании нового объекта из оператора приращения постфикса) этот новый объект помещается в отдельную ячейку памяти.

Однако в следующем коде a и b являются псевдонимами:

 int a = 0;
 int& b = ++a;

b - это адрес, который ссылается на a.

2 голосов
/ 05 июля 2010

Ваши операторы реализованы правильно.

В префиксном операторе копии X не создаются.

В постфиксном операторе одна копия создается для ret, а потенциально другая копия создается при возвращении из функции, но все компиляторы исключают эту копию.

...