Почему оператор присваивания должен возвращать ссылку на объект? - PullRequest
16 голосов
/ 31 января 2012

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

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

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

Ответы [ 3 ]

18 голосов
/ 31 января 2012

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

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

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

13 голосов
/ 31 января 2012

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

x = y;

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

if ((x = y)) {

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

x = y = z;

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

8 голосов
/ 31 января 2012

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

  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
    }
    
...