Diiference between copy constructor and overloading = operator
Hi,
I am currently writing a matix calculations program where we have to implement =operator overloading and copy constructor.But I could see that the program is giving wrong output bcos there occured a confusion in copy constructor and =operator overloading.I would like to know whether we can implement both copy constructor and =operator overloading in a program.
Thanks and regards,
Anjana
the general rule is that a copy constructor is called when you initialize a new object with an existing object, regardless of whether the initialization uses the = notation or the () notation. Similarly, whenever you assign to an existing object, the assignment operator is called, never the copy ctor.
I haven't tested your program. Can you tell which results are wrong?
I have taken 2 matrices a and b and the result after addition is saved in matrix d.After the result is saved in d,I could find that matrix a and b values also has been changed to the resultant matrix.When I debugged,I could see that after +operator is called for addition,copy constructor is also executed.I am not able to get this logic as why copy constructor is called soon after addition.
Your assignment moves these pointers:
array = whatever.array; ///now, THIS and THAT are pointing to the same memory location, so if you modify THIS, THAT changes, if you modify THAT, THIS changes. Not good!!
You absolutely MUST make copies of the data at some point, not just swap pointers. There will be times in your code where swapping pointers is faster but most of your assignments need to be raw data copys instead.
Let me suggest:
Matrix& operator=(Matrix obj)
{
// ALLOCATE MEMORY FOR THIS TO ENSURE IT IS BIG ENOUGH FOR OBJ
//DONT FORGET TO FREE EXISTING MEMORY
rows=obj.rows;
cols=obj.cols;
//array=obj.array; pointer chaos removed
for(int r = 0; r < rows; r++)
for(int c = 0; c < cols; c++)
array[r][c] = obj.array[r][c];
return *this;
}
Now, I don't know what this is for, but you are very likely making your life harder than it needs to be with double pointers and excessive data movement. If you need to make this stuff faster, let me know. Faster or not, I cannot recommed enough using a single dimensional pointer for array to reduce some of the excessive looping.
double * array = new double[rows*cols];
//arrray [5][6] can be reached with:
array[5*cols+6]; //you get used to it.
Now, something like add becomes:
for(int i = 0; i < rows*cols; i++)
result[i] = a[i] + b[i]; //an entire for loop eliminated.
On top of this, imagine you want to assign a 3X5 the result of something that is a 5X2. It will fit into the data, you need to put 10 numbers into 15 locations so thats fine. BUT, using your method, you cannot because you have too few rows in the destination, you must reallocate your memory. If you go my way, you can re-use the memory (check, yes its big enough, move along). Also, you can do things like transpose in place without reallocations, etc.
From the below explanation what I understood is :
Matrix d(a) and Matrix b(a) is pointing to the same memory location.So what ever changes made by matrix d,it is reflected in matrix a and b.Please correct me if I am wrong.
The reason why I am using double pointers is I was given the below assignment by my mentor.
• Implement addition and multiplication operation
• row and col of matrix is dynamic. So it should not be hard coded
• Implement copy constructor and copy assignment operator
• Implement post and pre increment / decrement operators to increment / decrement each elements in the matrix
• Overload the ostream << operator
• Private members will be as follows
o Int rows;
o Int cols;
o Int **array;
As far as I know I have implemented everything but the confusion in copy constructor and =operator overloading gives a different o/p,if we add the matrices for the second time.
I have tried to give the declarations as
Matrix d=a;
so that both dont point to same memory location.but the o/p is still the same.I have also given the =operator overloading definition as suggested.For all the cases,the addition result is correct for the first time,but soon after that matrix a and b copies the resultant matrix.
The main point is:
If you declare and intitialise an object like this
Code:
Matrix obj1;
Matrix obj2 = obj1; // declare and initialise obj2
Matrix obj3(obj1); // declare and initialise obj3
that is *NOT* done using the assignment operator, but the copy constructor.
Both obj2 and obj3 are being initialised using the copy-constructor.
Once your objects are declared and you assign one the othe, then the assignment operator is used
Code:
Matrix obj1;
Matrix obj2 = obj1; // declare and initialise obj2
Matrix obj3(obj1); // declare and initialise obj3
obj1 = obj3; // here the assignment operator is used
We could further confuse you by telling you what happens if you have implicit conversions in your class, but you better get you head around this...
Last edited by drkybelk; 07-03-2009 at 04:13 AM.
DKyb
-------------------------------
Life is a short warm moment -
Death is the long cold rest. Pink Floyd
-------------------------------
From the below explanation what I understood is :
Matrix d(a) and Matrix b(a) is pointing to the same memory location.So what ever changes made by matrix d,it is reflected in matrix a and b.Please correct me if I am wrong.
The reason why I am using double pointers is I was given the below assignment by my mentor.
• Implement addition and multiplication operation
• row and col of matrix is dynamic. So it should not be hard coded
• Implement copy constructor and copy assignment operator
• Implement post and pre increment / decrement operators to increment / decrement each elements in the matrix
• Overload the ostream << operator
• Private members will be as follows
o Int rows;
o Int cols;
o Int **array;
As far as I know I have implemented everything but the confusion in copy constructor and =operator overloading gives a different o/p,if we add the matrices for the second time.
I have tried to give the declarations as
Matrix d=a;
so that both dont point to same memory location.but the o/p is still the same.I have also given the =operator overloading definition as suggested.For all the cases,the addition result is correct for the first time,but soon after that matrix a and b copies the resultant matrix.
Well if the assignment demands ** then you use **, but I would tell him its a bad idea =)
Not sure what you are still doing, but the reason they are the same data is because of pointer goofs, it has to be. You have to be very precise and ensure that every class has a pointer that it creates and maintains and that pointer must *never* be assigned another pointer that is the data of another class (for now, later, you can set it up to allow this if you have a need, but for now consider that to be an error). You must only assign data and not pointers, if you do this, the problem should clear up.
Very simply:
if your copy CTOR has
array = incoming.array;
its wrong.
if your operater = has
array = incoming.array;
its wrong.
If any other function has
array = another_object.array;
its wrong.
These must all be loops, and with **, they must be double loops. To be 100% precise, this is what is required:
if ((row != incoming.rows) || (cols != incoming.cols)
for(i = 0; i < rows; i++)
delete[] array[i]; ///deletes all the column pointers
delete[] array; ///delets the row pointer
After reading all the comments,I understood the pointer **array was causing all the problems.So I simply declared array as normal array,ie,int array[10][10];
And it solved the problem.I hope I can put the pointer declaration as a limitation.:).
i couldnt find another way to solve it.
Part of your assignment is to make row and col sizes dynamic. 'fraid you can't do that with arrays.... Your instructor specifically wanted you to think about neccessary memory management - a key skill when programming in C++. I guess you'll have to try to make it work with double pointers. He gave you valuable hints though. Whenever you have pointer - member - variables you should create the four standard methods: def con, copy con, asgnmt and destr (which you did, I believe). You need to pay attention, though as to what those are supposed to do and what they actually do. ;-) This will become second nature soon enough and you will save yourself a lot of grief if you learn it now properly, believe me!
DKyb
-------------------------------
Life is a short warm moment -
Death is the long cold rest. Pink Floyd
-------------------------------
I am willing to learn more on this.Could anyone please give an example program where a double pointer class varaible can be accessed effectively using copy constructor ?
Thanks in advance,
Anjana
If you go there, let me at least suggest tracking (in a private variable in the class) the true rows and cols of the matrix (how large the allocated memory is currently, this is being done currently) and let the public rows and cols (not currently present) be anything smaller than the true ones (and, if the public ones are not directly settable by the user, the math functions at least should change them and any copy operations should be able to change them).
For example, if you had allocated matrix M as a 10 X 10, and the result of your multiply is a 4 X 7, allow it to be copied/assigned into M (instead of the hard == comparision on rows, cols, use <= or < depending on your logic). The true rows and cols would remain 10 X 10 and the public ones would be 4 X 7. This saves a pointless re-allocation (destroy 10X10 and create a 4X7) upon size change when the memory was plenty big enough. Keeping the size of the memory allocated seperate from the mathematical concept of dimensions will help a lot in many ways -- there are iterative/recursive routines that lop off a row or column until its a 2X2 or 3X3 and then pop back out, for example. It also allows you to allocate the memory to the largest possible size in your system, so you never need to re-allocate a matrix (if you want to use the time/space tradeoff of wasted space to prevent reallocations --it opens the door to *do* that or not as a choice).
if you use = you will get a unnessesary call to the base constructor, but with () you can get a slight performance bonus,as the VTBL already has the possible types figured out.
if you use = you will get a unnessesary call to the base constructor, but with () you can get a slight performance bonus
if an object is initialized with an other object of exactly the same type (using a copy constructor), both forms of the initializer will generate identical code.
struct A
{
static int n ;
virtual int foo() const { return ++n ; }
} ;
int A::n = 0 ;
struct B : A
{
static int n ;
virtual int foo() const { return --n ; }
} ;
void foo( A existing_object )
{
A new_object( existing_object ) ;
}
void bar( A existing_object )
{
A new_object = existing_object ;
}
extract of assembly listing generated by
g++ -c -g -Wa,-a,-ad -fomit-frame-pointer -Wall -werror -std=c++98 init.cc > init.asm
Bookmarks