Main Content

*this not returned in copy assignment operator

operator= method does not return a pointer to the current object

Description

This defect occurs when assignment operators such as operator= and operator+= do not return a reference to *this, where this is a pointer to the current object. If the operator= method does not return *this, it means that a=b or a.operator=(b) is not returning the assignee a following the assignment.

For instance:

  • The operator returns its parameter instead of a reference to the current object.

    That is, the operator has a form MyClass & operator=(const MyClass & rhs) { ... return rhs; } instead of MyClass & operator=(const MyClass & rhs) { ... return *this; }.

  • The operator returns by value and not reference.

    That is, the operator has a form MyClass operator=(const MyClass & rhs) { ... return *this; } instead of MyClass & operator=(const MyClass & rhs) { ... return *this; }.

Risk

Users typically expect object assignments to behave like assignments between built-in types and expect an assignment to return the assignee. For instance, a right-associative chained assignment a=b=c requires that b=c return the assignee b following the assignment. If your assignment operator behaves differently, users of your class can face unexpected consequences.

The unexpected consequences occur when the assignment is part of another statement. For instance:

  • If the operator= returns its parameter instead of a reference to the current object, the assignment a=b returns b instead of a. If the operator= performs a partial assignment of data members, following an assignment a=b, the data members of a and b are different. If you or another user of your class read the data members of the return value and expect the data members of a, you might have unexpected results. For an example, see Return Value of operator= Same as Argument.

  • If the operator= method returns *this by value and not reference, a copy of *this is returned. If you expect to modify the result of the assignment using a statement such as (a=b).modifyValue(), you modify a copy of a instead of a itself.

Fix

Return *this from your assignment operators.

Examples

expand all

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 */
        }
}

In this example, the operator operator= returns its current argument instead of a reference to *this.

Therefore, in main, the assignment r1 = r0 returns r0 and not r1. Because the operator= does not copy the data member m_b, the value of r0.m_b and r1.m_b are different. The following unexpected behavior occurs.

What You Might ExpectWhat Actually Happens
  • The statement (r1 = r0).isOk() returns r1.m_b which has value false

  • The if block does not execute.

  • The statement (r1 = r0).isOk() returns r0.m_b which has value true

  • The if block executes.

Correction — Return *this

One possible correction is to return *this from 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 */
        }
}

Result Information

Group: Object oriented
Language: C++
Default: Off
Command-Line Syntax: RETURN_NOT_REF_TO_THIS
Impact: Low

Version History

Introduced in R2015b