Assignment operator

why do we Check for self-assignment during the overloading of assignment operator ???
means

Cents& Cents::operator= (const Cents &cSource)
{
// check for self-assignment by comparing the address of the
// implicit object and the parameter
if (this == &cSource)
return *this;

// do the copy
m_nCents = cSource.m_nCents;

// return the existing object
return *this;
}

my question is why we use

if (this == &cSource)
return *this;

For trivial assignment operators like that... it really doesn't matter whether you do it or not. In fact... you probably don't even need to write that assignment operator... as the compiler-provided default will do the same.


For more complicated assignment operators, it prevents you from freeing memory or destroying resources you are still using. Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Foo
{
    int* dynamicdata;
    int size;

public:
    Foo(int s)
    {
        size = s;
        dynamicdata = new int[size];
    }
    ~Foo()
    {
        delete[] dynamicdata;
    }

    Foo& operator = (const Foo& rhs)
    {
        if(this == &rhs)  return *this;  // <- now this is very important!

        size = rhs.size;
        delete[] dynamicdata;
        dynamicdata = new int[size];

        std::copy( /*... copy stuff from rhs.dynamicdata to dynamicdata ...*/ );

        return *this;
    }
};


Without checking for self assignment... the delete[] on line 22 would delete our buffer! This would destroy the data for this object.

Normally that's okay because we're replacing that data with data obtained from the 'rhs' object... but if that 'rhs' object is the same as this one... then we've just destroyed that data!
┬┐why do you code an assignment operator when the default provided by the compiler is good enough?

You need to check for self-assignment if self-assignment is dangerous
Consider
1
2
3
4
5
6
7
8
9
10
11
12
13
class foo{
   char *buffer;

   foo& operator=(const foo &b){
      delete[] buffer;
      buffer =  new char[strlen(b.buffer)];
      strcpy( buffer, b.buffer );
      return *this;
   }
};

foo bar;
bar = bar;
I would prefer the copy and swap idiom for assignment operators, which alleviates the concern.

http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Copy-and-swap
Last edited on
Or with C++11, copy and move.

Though checking for self assignment is still often a good idea as an optimization (if the copy is expensive).
Topic archived. No new replies allowed.