Menu
C++ Tutorials

C++

Copy Constructors



Tutorials > C++ > Copy Constructors

View Full Source

What is a Copy Constructor?

Recall that in tutorial 23 we spoke about what happens when you pass a parameter by value. A copy of the variable is made.

When this happens, a shallow copy copy is made. This means that the values of all variables are copied directly from the original object or data type. What is wrong with this? A problem exists if you are using dynamic memory. In a shallow copy, the value of the pointer is copied. This means that the copy made will point to the same data of the original object or variable. This may not be what you are looking for. A deep copy must therefore be done. This can be accomplished using a copy constructor.

How is a Copy Constructor declared?

A copy constructor takes the form :

    Class_Name(const Class_Name &var);

Contents of main.cpp :


#include <iostream>
#include <stdlib.h>
#include <string>

using namespace std;

Once again we create a Player class.

class Player
{

public :

	Player(char *name);
	~Player();

Our copy constructor is declared below.

	// Copy Constructor
	Player(const Player &rhs);

The rest of the class is declared as per normal.

	const char *getName() const
	{ return name; }

	void printKillList();

	string *getKillList() const
	{ return killList; }
	int getNumKills() const
	{ return numKills; }
	
private :

	char name[50];
	int health;
	int mana;

	int numKills;
	string *killList;
};

The constructor allocates memory for 3 names forming a list of the enemies that have been killed.

Player::Player(char *n) : health(100), mana(50) 
{
	strcpy(name, n);
	numKills = 3;
	killList = NULL;
	killList = new string[3];
	killList[0] = "Bob";
	killList[1] = "John";
	killList[2] = "James";
}

The destructor reclaims the memory previously allocated.

Player::~Player()
{
	delete[] killList;
	killList = NULL;
}

The following method prints out the names in the kill list.

void Player::printKillList()
{
	for (int i = 0; i < numKills; i++)
		cout << killList[i] << endl;
}

The body of our copy constructor is given below.
Firstly, the name is copied. Secondly, memory for the new kill list is allocated and all values in the list are copied from the original object. A message is also displayed to show that the copy constructor is visited.

Player::Player(const Player &rhs)
{
	cout << "Copy Constructor" << endl;

	strcpy(name, rhs.getName());

	this->numKills = rhs.getNumKills();

	killList = new string[numKills];

	string *rhsKillList = rhs.getKillList();

	for (int i = 0; i < numKills; i++)
		killList[i] = rhsKillList[i];
}

The function below takes a Player object as a parameter. Calling this method will result in a Player object being copied.

void printKillList(Player p)
{
	cout << p.getName() << endl;
	
	for (unsigned int i = 0; i < strlen(p.getName()); i++)
		cout << "-";

	cout << endl;

	p.printKillList();
}

The code below simply passes a Player object to a function. The kill list is printed out.

If you are still unsure why you need a copy constructor for dynamic memory, you can try removing the copy constructor. You will find that the list is printed out successfully, but afterwards the program will crash. This is because the object is passed to the function and the original data is used. At the end of the function, the copied object is destroyed but the destructor will end up deleting the data. As both objects pointed to the same data, all data is deleted. When the original object comes out of scope, the memory is reclaimed again, causing an error.

int main()
{
	Player fred("Fred");

	printKillList(fred);

	system("pause");

	return 0;
}

Congratulations. You should now understand why copy constructors are necessary and how they can be implemented.

Please let me know of any comments you may have : Contact Me

Source Files : Visual Studio Dev-C++ Unix / Linux

< Tutorial 51 - This Pointer Tutorial 53 - Operator Overloading >

Back to Top


All Rights Reserved, © Zeus Communication, Multimedia & Development 2004-2005

Read the Disclaimer

Links