Showing posts with label Copy Constructor. Show all posts
Showing posts with label Copy Constructor. Show all posts

Wednesday, 8 December 2010

Difference between Deep copy and Shallow copy in C++

So what is the difference between 'Deep copy' (sometimes referred to as 'Hard copy') and 'Shallow copy' in C++

Shallow copy: Copies the member values from one object into another.

Deep Copy: Copies the member values from one object into another. Any pointer objects are duplicated and Deep Copied.

There are some interesting discussions on Stack Overflow here and here. A related discussions here is interesting as well.

Program to demonstrate as follows:


//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include<iostream>
#include<string>

using namespace
std;

class
MyString
{

public
:
MyString(){}
MyString(string str)
{

size = str.size();
data = new char(size+1); //+1 for '\0'
memcpy(data, str.c_str(), size+1);
}

//MyString(const MyString& copy); - Use default for Shallow
void DeepCopy(const MyString& copy) //Deep Copy
{
size = copy.size;
data = new char(size+1); //+1 for '\0'
memcpy(data, copy.data, size+1);
}

int
size;
char
* data;
};


int
main()
{

MyString m1("Zahid");
cout<<"\nm1.size = "<<m1.size<<", &m1.data = "<<(void *)m1.data<<", *m1.data = "<<m1.data<<endl;

MyString m2(m1); //Uses the default copy constructor - Shallow Copy
cout<<"\nm2.size = "<<m2.size<<", &m2.data = "<<(void *)m2.data<<", *m2.data = "<<m2.data<<endl;

MyString m3; //Another default constructor
m3.DeepCopy(m1);
cout<<"\nm3.size = "<<m3.size<<", &m3.data = "<<(void *)m3.data<<", *m3.data = "<<m3.data<<endl;

return
0;
}


Output as follows:


Wednesday, 2 June 2010

Class initialisation and constructors

There is often lots of confusion with regards to class initialisation. People may forget to take care while using default constructors and copy constructors. Here is a simple example that tries to explain lots of concepts.





//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//This program gives an example of constructors and initialisations

#include<iostream>

using namespace
std;

//Example of a class
class someClass1
{

public
:
//implicit default constructor
int x;
int
*y;
};


//Example of a class with constructor
class someClass2
{

public
:
someClass2(const someClass2& xyz)
{

cout<<"** copy constructor called"<<endl;
x = xyz.x;
y = new int(*xyz.y);
}

//default constructor will have to be explicitly defined
someClass2() {};
//overloading operator '='
const someClass2& operator = (const someClass2& xyz)
{

cout<<"** operator '=' called"<<endl;
x = xyz.x;
y = new int(*xyz.y);
return
*this;
}

int
x;
int
*y;
};


int
main()
{

someClass1 a; //Default initialisation
a.x = 1234;
a.y = new int(6789);

cout<<"someClass1: a.x = "<<a.x<<" a.y( " <<a.y<< " ) = "<<*(a.y)<<endl;

someClass1 b = a; //Copy Initialisation

cout<<"someClass1: b.x = "<<b.x<<" b.y( " <<b.y<< " ) = "<<*(b.y)<<endl;

someClass1 c(a); //Direct Initialisation

cout<<"someClass1: c.x = "<<c.x<<" c.y( " <<c.y<< " ) = "<<*(c.y)<<endl;

//Calling default constructor
someClass2 aa;
aa.x = 2468;
aa.y = new int(3579);

cout<<"someClass2: aa.x = "<<aa.x<<" aa.y( " <<aa.y<< " ) = "<<*(aa.y)<<endl;

//calling copy constructor
someClass2 bb = aa; //Copy Initialisation - note copy constructor will be called

cout<<"someClass2: bb.x = "<<bb.x<<" bb.y( " <<bb.y<< " ) = "<<*(bb.y)<<endl;

//calling copy constructor
someClass2 cc(aa); //Direct Initialisation - note copy constructor called in this case as well

cout<<"someClass2: cc.x = "<<cc.x<<" cc.y( " <<cc.y<< " ) = "<<*(cc.y)<<endl;

someClass2 dd;
//calling operator =
dd = aa;

cout<<"someClass2: dd.x = "<<dd.x<<" dd.y( " <<dd.y<< " ) = "<<*(dd.y)<<endl;

return
0;
}







The output is as follows:

There are certain things worth noting in the above example:
  • In case of someClass1, since only the default constructor is used, the same pointer is used for y in all the cases. This can cause serious problems in the code if one of the classes delete the memory pointed by y for class someClass1. This problem is not present in someClass2
  • If any constructor is defined, it becomes necessary to define the default constructor. You can make sure that nobody uses default constructor in case of someClass2 by making it private (I havent done that because I wanted to show operator =)
  • As you can see in case of variable cc, copy constructor would always be called instead of operator =.
  • operator = would only be called in case of assignment. This is a common mistake.
  • In the code above, cc(aa) is better than using bb = aa even though the results are the same. The main advantage being that it will avoid confusion with operator '=' if its overloaded for a novice and the constructor can be overloaded to take more than one input in future.

Thursday, 18 June 2009

Copy Constructor and Assignment Operator

This example shows the Copy Constructor and the Assignment Operator. In the example, I have just relied on the Default Copy Constructor and the Default Assignment Operator. For a complex class, the default may not be a good option and they will have to be explicitly written.


//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include<iostream>

using namespace
std;

class
A {
public
:
int
x,y;
};


int
main()
{

A a;
a.x = 11;
a.y = 2222;

A a2(a); //Default Copy constructor called
//Copies a paramaters to a2
cout<<"a2 variables are: a2.x = "<<a2.x<<" and a2.y = "<<a2.y<<endl;

A a3;
a3 = a; //Default Assignment Operator called
//Copies a paramaters to a3
cout<<"a3 variables are: a3.x = "<<a3.x<<" and a3.y = "<<a3.y<<endl;

return
0;
}



The output is as follows: