Demo - Copy Constructor

Here is an example of a class with a copy constructor:

#include <iostream> #include <string> using namespace std; class Person { public: Person(string name, int age); Person(const Person& other); // Copy constructor void introduce(); private: string name; int age; }; Person::Person(string name, int age) { this->name = name; this->age = age; } Person::Person(const Person& other) { this->name = other.name; this->age = other.age; } void Person::introduce() { cout << "Hi, my name is " << name << " and I am " << age << " years old." << endl; } int main() { Person personOne("Alice", 25); // // Use copy constructor to create new object personTwo Person personTwo = personOne; personOne.introduce(); personTwo.introduce(); return 0; }

 

In this example, the Person class has a copy constructor that takes a reference to another Person object as its argument. Inside the copy constructor, the new Person object is created by copying the name and age from the original object.

In the main function, two Person objects are created: p1 and p2. p2 is initialized using the copy constructor by passing p1 as an argument. Both objects are then introduced using the introduce function, and the output shows that they have the same name and age.

Using copy constructors is important for creating new objects that are exact copies of existing objects, especially when working with large or complex objects. It is also necessary when passing objects by value to functions or returning them from functions.

The provided C++ code demonstrates the use of a copy constructor in a Person class:

  1. The Person class:

    • It has a private name (string) and age (int) member variables.

    • It declares a public constructor that takes name and age as parameters and initializes the member variables.

    • It declares a copy constructor that takes another Person object as a parameter.

    • It declares a public introduce() method that prints the person's name and age.

  2. The constructor Person::Person(string name, int age):

    • It initializes the name and age member variables of the Person object using the provided arguments.

  3. The copy constructor Person::Person(const Person& other):

    • It creates a new Person object by copying the name and age values from another Person object (other).

  4. The introduce() method:

    • It prints the person's name and age using cout.

  5. In the main() function:

    • Two Person objects, personOne and personTwo, are created.

    • personOne is initialized with the name "Alice" and age 25 using the constructor.

    • personTwo is initialized with personOne using the copy constructor.

    • The introduce() method is called for both personOne and personTwo, printing their respective details.

By using the copy constructor, personTwo is created as a copy of personOne. This allows for the creation of a new object with the same values as an existing object.


In this case, we'll consider a class String that has a raw pointer char* as a member. This is a case where we need a custom copy constructor to perform a deep copy.

#include <iostream> #include <cstring> using namespace std; class String { private: // buffer is a pointer to a character array. char* buffer; public: // Constructor - takes a const char* argument and dynamically // allocates memory for buffer using new[] to store the string // passed as an argument. String(const char* str) { buffer = new char[strlen(str) + 1]; strcpy(buffer, str); } // Copy Constructor - deep copy String(const String& pString) { buffer = new char[strlen(pString.buffer) + 1]; strcpy(buffer, pString.buffer); } //desctructor ~String() { delete[] buffer; } // returns a constant pointer to the character buffer. const char* getValue() const { return buffer; } }; int main() { // Create a string String strOne("Hello, World!"); // Copy string strOne into strTwo String strTwo = strOne; cout << "strOne: " << strOne.getValue() << endl; cout << "strTwo: " << strTwo.getValue() << endl; return 0; }

 

In the String class, we have a raw pointer buffer as a member. In the constructor, we allocate memory for buffer and copy the input string into buffer.

In the copy constructor, we also allocate new memory for buffer, ensuring it's a separate piece of memory from the original object's buffer. Then, we copy the content of the original object's buffer into the new buffer. This process is known as a "deep copy".

Finally, in the destructor, we free the memory that was allocated for buffer to prevent a memory leak.

The main function demonstrates the copy constructor. We create String strone and then use the copy constructor to create String strTwo as a copy of strOne. We then print out the values of strOne and strTwo to confirm they both contain the correct string.

The given C++ code demonstrates the implementation of a simplified String class with a dynamic character buffer:

  1. The String class:

    • It has a private member variable buffer, which is a pointer to a character array.

    • It includes a constructor that takes a const char* argument and dynamically allocates memory for buffer using new[] to store the string passed as an argument.

    • It includes a copy constructor that takes another String object as a parameter and performs a deep copy of the buffer by allocating memory and copying the contents from the source object.

    • It includes a destructor that frees the dynamically allocated memory using delete[].

    • It includes a getter function getValue() that returns a constant pointer to the character buffer.

  2. The constructor String::String(const char* str):

    • It determines the length of the input string using strlen().

    • It allocates memory for buffer with a size equal to the length of the input string plus one for the null terminator.

    • It copies the input string into buffer using strcpy().

  3. The copy constructor String::String(const String& s):

    • It determines the length of the source object's buffer using strlen().

    • It allocates memory for buffer with a size equal to the length of the source object's buffer plus one for the null terminator.

    • It copies the contents of the source object's buffer into buffer using strcpy().

  4. The destructor String::~String():

    • It frees the dynamically allocated memory for buffer using delete[].

  5. In the main() function:

    • An instance of String named strOne is created by passing the string "Hello, World!" to the constructor.

    • Another instance of String named strTwo is created by using the copy constructor and initializing it with strOne.

    • The values stored in strOne and strTwo are printed using the getValue() function.

This code demonstrates how to create a custom string class that manages dynamic memory allocation and provides the ability to copy objects correctly using the copy constructor and destructor.

 

An additional Example of the use of a Copy Constructor is in the Objects and Classes Section:

 

2024 - Programming 3 / Data Structures - Author: Dr. Kevin Roark