*это не возвращенное в операторе присваивания копии

Метод operator= не возвращает указатель на текущий объект

Описание

*this, не возвращенный в оператор присваивания копии, происходит, когда операторы присваивания, такие как operator= и operator+= не возвращают ссылку на *this, где this является указателем на текущий объект. Если метод operator= не возвращает *this, это означает, что a=b или a.operator=(b) не возвращают представителя a после присвоения.

Например:

  • Оператор возвращает свой параметр вместо ссылки на текущий объект.

    Таким образом, оператор имеет форму MyClass & operator=(const MyClass & rhs) { ... return rhs; } вместо MyClass & operator=(const MyClass & rhs) { ... return *this; }.

  • Оператор возвращается значением и не ссылкой.

    Таким образом, оператор имеет форму MyClass operator=(const MyClass & rhs) { ... return *this; } вместо MyClass & operator=(const MyClass & rhs) { ... return *this; }.

Риск

Пользователи обычно ожидают, что объектные присвоения будут вести себя как присвоения между встроенными типами и ожидать, что присвоение возвратит представителя. Например, правоассоциативное цепочечное присвоение, a=b=c требует, чтобы b=c возвратил представителя b после присвоения. Если ваш оператор присваивания ведет себя по-другому, пользователи вашего класса могут столкнуться с неожиданными последствиями.

Неожиданные последствия происходят, когда присвоение является частью другого оператора. Например:

  • Если operator= возвращает свой параметр вместо ссылки на текущий объект, присвоение, a=b возвращает b вместо a. Если operator= выполняет частичное присвоение элементов данных, после присвоения, a=b, элементы данных a и b отличаются. Если вы или другой пользователь вашего класса читаете элементы данных возвращаемого значения и ожидаете элементы данных a, у вас могут быть неожиданные результаты. Для примера смотрите Возвращаемое значение оператора = То же самое в качестве Аргумента.

  • Если метод operator= возвращает *this значением и не ссылкой, копия *this возвращена. Если вы ожидаете изменять результат присвоения с помощью оператора, такого как (a=b).modifyValue(), вы изменяете копию a вместо самого a.

Фиксация

Возвратите *this в свои операторы присваивания.

Примеры

развернуть все

class MyClass {
    public:
        MyClass(bool b, int i): m_b(b), m_i(i) {}
        const MyClass& operator=(const MyClass& obj) {
            if (&obj!=this) {
                /* Note: Only m_i is copied. m_b retains its original value. */
                m_i = obj.m_i;
            }
            return obj;
        }
        bool isOk() const { return m_b;}
        int getI() const { return m_i;}
    private:
        bool m_b;
        int m_i;
};

void main() {
        MyClass r0(true, 0), r1(false, 1);
        /* Object calling isOk is r0 and the if block executes. */
        if ( (r1 = r0).isOk()) {
            /* Do something */
        }
}

В этом примере оператор operator= возвращает свой текущий аргумент вместо ссылки на *this.

Поэтому в main, присвоение r1 = r0 возвращает r0 и не r1. Поскольку operator= не копирует элемент данных, m_b, значение r0.m_b и r1.m_b отличаются. Следующее неожиданное поведение происходит.

Что вы можете ожидатьЧто на самом деле происходит
  • Оператор (r1 = r0).isOk() возвращает r1.m_b, который имеет значение false

  • Блок if не выполняется.

  • Оператор (r1 = r0).isOk() возвращает r0.m_b, который имеет значение true

  • Блок if выполняется.

Исправление — возвращает *this

Одно возможное исправление должно возвратить *this в operator=.

class MyClass {
    public:
        MyClass(bool b, int i): m_b(b), m_i(i) {}
        const MyClass& operator=(const MyClass& obj) {
            if (&obj!=this) {
                /* Note: Only m_i is copied. m_b retains its original value. */
                m_i = obj.m_i;
            }
            return *this;
        }
        bool isOk() const { return m_b;}
        int getI() const { return m_i;}
    private:
        bool m_b;
        int m_i;
};

void main() {
        MyClass r0(true, 0), r1(false, 1);
        /* Object calling isOk is r0 and the if block executes. */
        if ( (r1 = r0).isOk()) {
            /* Do something */
        }
}

Информация о результате

Группа: Объектно-ориентированный
Язык: C++
Значение по умолчанию: 'off'
Синтаксис командной строки: RETURN_NOT_REF_TO_THIS
Влияние: низко

Введенный в R2015b