2012-06-01

C++: Operator= returns const reference of *this or reference of *this?

Abstract

Recently, I started to use cppcheck. cppcheck suggested me that the return type of operator= should reference of (*this). But I thought this should be const reference of (*this). I thought the reason of this.

Contents

Cppcheck is an static analysis tool for C/C++ code. (http://cppcheck.sourceforge.net/) I found this tool is quite useful since it sometimes finds a memory leak error and so on. However, the following code has some style error at the operator=.

#include 
class OpTest {
public:
    /// constructor
    OpTest(int init_int) : m_int(init_int){
        // empty
    }
    /// operator= with const reference
    OpTest const & operator=(OpTest const & rhs){
        if(this != &rhs){
            m_int = rhs.m_int;
        }
        return *this;
    }
public:
    int m_int;
};

cppcheck said:
[operator_substitute_00.cpp:9]: (style) 'OpTest::operator=' should return 'OpTest &'.
I thought when I finished substitution of an instance, I consider the instance (= *this) should be const. Therefore, I was puzzled when I saw this message. I look up web, but I could not find a page that explains why this should be. Although, many of code returns just a reference of (*this).

I asked several colleagues about this. Then Ali answered me that: maybe you can call the non const method after the substitution. The following code is an example.
OpTest a(0);
OpTest b(1);
(a = b).non_const_method();
I see a point, but personally, I would prefer the following code.
OpTest a(0);
OpTest b(1);
a = b;
a.non_const_method();

2 comments:

Daniel Marjamäki said...

Hi!

I am a cppcheck developer and I saw this post.

Yes there are good safety reasons to use const. But I still recommend that you don't use const.

The reason you should return a non-const reference is for consistency. That is how the old C types such as int, char, short, etc work. That is how the C++ types such as std::string, std::vector, etc work.

This is valid C code:
int a = 1, b = 2;
int &c = (a = b);
c = 3; // modify a

Similar code can be written using std::string, std::vector, etc.

Regards, Daniel

Shitohichi said...

Thanks for the comment. I see now why cppcheck suggests this.

Also thanks for the cppcheck, that's a great free software.