Assignment operaor

T

Tony Johansson

Hello!

Assume I have the following two classes Student and InfoStudent and its
definition below.
In the definition of the assignment operator that is defined I can remove
these two lines
if (this == &s)
return *this;

when I have done this is main which is assign to myself
InfoStudent is(1);
is = is;

and it work just as good as with them. So what's the point having them?.
Here is my explanation why is works.
First the left side resouces is deleted here the Student object rep_
then a new student object pointer rep_ is created with new passing the
student number from the right operand s.
So why have this
if (this == &s)
return *this;
if it's work all the same without when I assign an object to my self as I
hade done with object is=is;


//Tony


Definition of assignment operator
*************************
InfoStudent& InfoStudent::eek:perator=(const InfoStudent& s)
{
if (this == &s)
return *this;
delete rep_;
rep_ = new Student(s.number());
return *this;
}

class definitions
************
class Student
{
public:
Student(long);
void number(long);
long number() const;
private:
long number_;
};

class InfoStudent
{
public:
InfoStudent(long);
InfoStudent(const InfoStudent&);
~InfoStudent();
InfoStudent& operator=(const InfoStudent&);
long number() const;
private:
Student* rep_;
};
 
R

Rolf Magnus

Tony said:
Hello!

Assume I have the following two classes Student and InfoStudent and its
definition below.
In the definition of the assignment operator that is defined I can remove
these two lines
if (this == &s)
return *this;

when I have done this is main which is assign to myself
InfoStudent is(1);
is = is;

and it work just as good as with them.

It might appear to work, but it's still wrong.
So what's the point having them?.
Here is my explanation why is works.
First the left side resouces is deleted here the Student object rep_
then a new student object pointer rep_ is created with new passing the
student number from the right operand s.

The part that you're missing is that - when self-assigning - the rep_ member
of the right hand side is the same as the rep_ member of the left hand
side. So what happens is that you first delete the Student object, then
create a new one, and then try to copy the data from the deleted one to the
new one.

It might still work if the compiler decides to just mark the deleted memory
as unused and keep its value. Then it appears as if the object were still
there. However, your code should never depend on such behavior.
 
T

Tony Johansson

You say
The part that you're missing is that - when self-assigning - the rep_
member
of the right hand side is the same as the rep_ member of the left hand
side. So what happens is that you first delete the Student object, then
create a new one, and then try to copy the data from the deleted one to
the
new one.


You write "try to copy the data from the deleted one to the
new one" but that is wrong. I never copy data from the deletes one.
Insted I copy data from the right side which in this case is parameter s.

So that was wrong explanation!

//Tony
 
C

Chris Theis

Tony said:
You say




You write "try to copy the data from the deleted one to the
new one" but that is wrong. I never copy data from the deletes one.
Insted I copy data from the right side which in this case is parameter s.

So that was wrong explanation!
[SNIP]

No it wasn't. If you perform self assignment "s" will be just a
different name for the original object (which is essentially what self
assignment means). Hence, you're walking on thin ice here, just as Rolf
pointed out. Try to step through your code with a debugger and check the
addresses of the left and the right hand side of the copy ctor when
performing self assignment, and you'll see.

Cheers
Chris
 
J

John Carson

Tony Johansson said:
You say


You write "try to copy the data from the deleted one to the
new one" but that is wrong. I never copy data from the deletes one.
Insted I copy data from the right side which in this case is
parameter s.
So that was wrong explanation!

Not convinced. Below is your code in a compileable order.
class definitions
************
class Student
{
public:
Student(long);
void number(long);
long number() const;
private:
long number_;
};

class InfoStudent
{
public:
InfoStudent(long);
InfoStudent(const InfoStudent&);
~InfoStudent();
InfoStudent& operator=(const InfoStudent&);
long number() const;
private:
Student* rep_;
};
Definition of assignment operator
*************************
InfoStudent& InfoStudent::eek:perator=(const InfoStudent& s)
{
if (this == &s)
return *this;
delete rep_;
rep_ = new Student(s.number());
return *this;
}

You call s.number() as the argument of the Student constructor. s is a
reference to an InfoStudent but there is no data member in InfoStudent for
storing a number. There is, however, such a data member in Student. I am
therefore guessing that s.number() actually gets the value it returns from
calling _rep->number(). In that case you are indeed copying data from a
deleted object.

If this is true, you could in fact work around this with the following:

InfoStudent& InfoStudent::eek:perator=(const InfoStudent& s)
{
long temp = s.number();
delete rep_;
rep_ = new Student(temp);
return *this;
}

This, however, like self assignment in general, is a pointless waste of CPU
cycles. Self assignment is not illegal but, with rare exceptions, the best
you can hope for is that it does nothing. The worst that can happen is data
corruption and/or a crash.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,203
Messages
2,571,059
Members
47,668
Latest member
SamiraShac

Latest Threads

Top