Detail the C++ copy constructor

  • 2020-10-23 20:13:57
  • OfStack

A copy constructor is a special constructor that, when creating an object, initializes the newly created object using the object previously created in the same class. Copy constructors are commonly used for:

Initializes the newly created object by using another object of the same type. The copy object passes it to the function as an argument. Copy the object and return it from the function.

If no copy constructor is defined in the class, the compiler defines one itself. If the class has pointer variables and dynamic memory allocation, it must have a copy constructor. The most common form of a copy constructor is as follows:


classname (const classname &obj) {
  //  The body of the constructor 
}

In this case, obj is an object reference that is used to initialize another object.


#include <iostream>
 
using namespace std;
 
class Line
{
  public:
   int getLength( void );
   Line( int len );       //  Simple constructor 
   Line( const Line &obj);   //  Copy constructor 
   ~Line();           //  The destructor 
 
  private:
   int *ptr;
};
 
//  Member function definitions, including constructors 
Line::Line(int len)
{
  cout << " Call constructor " << endl;
  //  Allocate memory for Pointers 
  ptr = new int;
  *ptr = len;
}
 
Line::Line(const Line &obj)
{
  cout << " Call the copy constructor and call the pointer  ptr  Allocate memory " << endl;
  ptr = new int;
  *ptr = *obj.ptr; //  Copy the value 
}
 
Line::~Line(void)
{
  cout << " Free memory " << endl;
  delete ptr;
}
int Line::getLength( void )
{
  return *ptr;
}
 
void display(Line obj)
{
  cout << "line  The size of the  : " << obj.getLength() <<endl;
}
 
//  The main function of the program 
int main( )
{
  Line line(10);
 
  display(line);
 
  return 0;
}

When the above code is compiled and executed, it produces the following results:

[

Call constructor
Call the copy constructor and allocate memory for the pointer ptr
line size: 10
Free memory
Free memory

]

The following instance slightly modifies the above instance by initializing the newly created object by using an existing object of the same type:


#include <iostream>
 
using namespace std;
 
class Line
{
  public:
   int getLength( void );
   Line( int len );       //  Simple constructor 
   Line( const Line &obj);   //  Copy constructor 
   ~Line();           //  The destructor 
 
  private:
   int *ptr;
};
 
//  Member function definitions, including constructors 
Line::Line(int len)
{
  cout << " Call constructor " << endl;
  //  Allocate memory for Pointers 
  ptr = new int;
  *ptr = len;
}
 
Line::Line(const Line &obj)
{
  cout << " Call the copy constructor and call the pointer  ptr  Allocate memory " << endl;
  ptr = new int;
  *ptr = *obj.ptr; //  Copy the value 
}
 
Line::~Line(void)
{
  cout << " Free memory " << endl;
  delete ptr;
}
int Line::getLength( void )
{
  return *ptr;
}
 
void display(Line obj)
{
  cout << "line  The size of the  : " << obj.getLength() <<endl;
}
 
//  The main function of the program 
int main( )
{
  Line line1(10);
 
  Line line2 = line1; //  The copy constructor is also called here 
 
  display(line1);
  display(line2);
 
  return 0;
}

When the above code is compiled and executed, it produces the following results:

[

Call constructor
Call the copy constructor and allocate memory for the pointer ptr
Call the copy constructor and allocate memory for the pointer ptr
line size: 10
Free memory
Call the copy constructor and allocate memory for the pointer ptr
line size: 10
Free memory
Free memory
Free memory

]

Why does 1 have to have a total definition copy constructor when a class member contains a pointer type member and needs to allocate memory to it??

The default copy constructor implements only shallow copy, which directly copies the data member values of the original object to the corresponding data members in the new object in turn, without allocating additional memory resources to the new object.

Thus, if an object's data member is a pointer, both pointer objects are actually pointing to the same block of memory space.

In some cases, shallow copy back can lead to data security concerns.

When there is a pointer type in the data member of a class, we must define a specific copy constructor that not only implements a copy of the data member between the original object and the new object, but also allocates a separate memory resource for the new object. This is called a deep copy constructor.

How do I prevent default copies from happening

Declare a private copy constructor so that because the copy constructor is private, the compiler will report an error if the user tries to pass or return an object of the class by value, thereby avoiding passing or returning an object by value.

Conclusion:

The copy function is called when an equal value is assigned to the class, and the default copy function -- shallow copy -- is called when the display copy constructor is not defined, which completes the 11 copy of the member. Shallow copy is possible when there are no Pointers in the data member. But when there are Pointers in a data member, if a simple shallow copy is used, two Pointers in both classes will point to the same address, and the destructor will be called twice at the end of the object, resulting in pointer suspension. So, at this point, you have to use a deep copy.

The difference between a deep copy and a shallow copy is that a deep copy creates extra space in the heap to store the data, thus solving the pointer hanging problem. In short, you must use a deep copy when there are Pointers in a data member.

That's how C++ copy constructors are explained in detail. For more information on C++ copy constructors, check out the other articles on this site!


Related articles: