exponenta event banner

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

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

Описание

Этот дефект возникает, когда операторы назначения, такие как 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++
По умолчанию: Откл.
Синтаксис командной строки: RETURN_NOT_REF_TO_THIS
Воздействие: Низкий
Представлен в R2015b