15

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

class Foo 
{ 
    public: 
     int x; 
     int y; 
     void operator=(const Foo&); 
}; 
void Foo::operator=(const Foo &rhs) 
{ 
    x = rhs.x; 
    y = rhs.y; 
} 

Во всех ссылках, которые я нашел в Интернете, я заметил, что оператор возвращает ссылку на объект источника. Почему правильный способ вернуть ссылку на объект, а не на ничего?

+0

Правильный путь любым способом реализует семантику вы хотите; путь _idiomatic_, безусловно, должен возвращать 'T &' ('Foo &' в вашем примере). – ildjarn

+0

@MooingDuck, я думаю, я сформулировал вопрос неправильно. Я исходил из того, что мои заметки были неправильными, но хотел знать, почему больше, чем было правильно. – maccard

+1

Возможный дубликат [оператор присваивания возвращает ссылку на * это в C++] (http://stackoverflow.com/questions/5669813/assignment-operator-return-a-reference-to-this-in-c); также [Возврат * с оператором присваивания] (http://stackoverflow.com/questions/3248469/returning-this-with-an-assignment-operator) –

ответ

17

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

Foo a, b, c; 
// ... 
a = b = c; 

Тем не менее, имейте в виду, что получение правильного оператора распайка is tougher than it might seem.

+0

Никогда не знал о части Copy and Swap. Я всегда просто проверял самоназначение, присваивал значения и возвращал пустоту, я думаю, что в этом есть нечто большее, чем я ожидал. Принимая ваш ответ за указание Копировать & Swap Спасибо за ответ. – maccard

13

Возвращение типа не имеет значения, когда вы только выполнение одного задания в заявлении, как это:

x = y; 

Он начинает иметь значение, когда вы делаете это:

if ((x = y)) { 

. .. и действительно имеет значение, когда вы это делаете:

x = y = z; 

Именно поэтому вы возвращаете текущий объект: всем назначение цепочки с правильной ассоциативностью. Это хорошая общая практика.

+0

Я не понимаю, почему вы говорите «это начинает иметь значение». Либо это имеет значение, либо нет. Не могли бы вы рассказать? – balajeerc

+3

@balajeerc: «Это начинает иметь значение» на английском языке означает, что «это имеет значение в последней ситуации, но не в первом». Другими словами, «при переходе от ситуации А к В значение важности (« важности ») переходит от нуля к ненулевому». В прямом назначении возвращение не имеет значения. Внутри условного значения имеет значение, если вещь, которую вы возвращаете, является истиной или ложной, но не точно, какой именно объект. В случае с цепочкой назначений вы действительно хотите, чтобы return был текущим объектом, потому что в противном случае результаты были бы противоречивыми. – Borealid

8

Ваш оператор присваивания должен всегда делать эти три вещи:

  1. Возьмите Уст-вход задания (const MyClass &rhs) в правой части задания. Причина этого должна быть очевидной, поскольку мы не хотим случайно изменить это значение; мы хотим только изменить то, что находится на левой стороне.

  2. Всегда возвращайте ссылку на недавно измененную левую сторону, return *this. Это должно позволить цепочку операторов, например. a = b = c;.

  3. Всегда проверяйте самоподключение (this == &rhs). Это особенно важно, когда ваш класс выполняет собственное распределение памяти.

    MyClass& MyClass::operator=(const MyClass &rhs) { 
        // Check for self-assignment! 
        if (this == &rhs) // Same object? 
         return *this; // Yes, so skip assignment, and just return *this. 
    
        ... // Deallocate, allocate new space, copy values, etc... 
    
        return *this; //Return self 
    } 
    
+1

Проверка самоназначения - наивное решение, правильное - копирование и своп. –

+0

Спасибо за ответ, но я просто пытался сделать простой пример, оставив проверку самоопределения. Я все понял, возвращая ссылку. – maccard

+0

@MatteoItalia Копирование и своп могут быть дорогими. Например, назначение одного большого вектора другому не может повторно использовать память цели, если используется копирование и своп. –

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