Explaining copy constructor example

35,083

Solution 1

The argument to the display() function is passed by value, so the compiler calls the copy constructor to create it. When the class defines its copy constructor you get the correct semantics: the copy constructor makes a copy, and that copy has its own memory to hold the length. When you remove the copy constructor, the compiler generates one for you, and the copy that gets passed to display() has the same pointer as the original. When that copy gets destroyed it deletes the memory that ptr points to. When the original gets destroyed it deletes the same memory again (which happens to have no visible effects here). That's definitely not what you want to have happen, which is why you need to define a copy constructor. As @Joe says: inside the destructor, print the value of `ptr' to see this more clearly.

Solution 2

Print the address of the memory being freed.

I believe you will find the compiler generated the constructor for you, did a value copy of the contents, including the pointer, and you are double-freeing the pointer and just getting lucky that the runtime isn't complaining about it.

The compiler generated copy constructor is still being called - nothing has changed in that regard, you just aren't printing anything from it since you didn't write it.

Solution 3

If we don’t define our own copy constructor, the C++ compiler creates a default copy constructor for each class which does a member wise copy between objects. The compiler created copy constructor works fine in general. We need to define our own copy constructor only if an object has pointers or any run time allocation of resource like file handle, a network connection..

Share:
35,083
Omar
Author by

Omar

Updated on July 09, 2022

Comments

  • Omar
    Omar almost 2 years

    A copy constructor is used for many things such as when I need to use pointers or dynamically allocate memory for an object. But looking at this example at tutorialpoint.com:

    #include <iostream>
    
    using namespace std;
    
    class Line
    {
    public:
      int getLength( void );
      Line( int len );             // simple constructor
      Line( const Line &obj);  // copy constructor
      ~Line();                     // destructor
    
    private:
      int *ptr;
    };
    
    // Member functions definitions including constructor
    Line::Line(int len)
    {
    cout << "Normal constructor allocating ptr" << endl;
    // allocate memory for the pointer;
    ptr = new int;
    *ptr = len;
    }
    
    Line::Line(const Line &obj)
    {
    cout << "Copy constructor allocating ptr." << endl;
    ptr = new int;
    *ptr = *obj.ptr; // copy the value
    }
    
    Line::~Line(void)
    {
    cout << "Freeing memory!" << endl;
    delete ptr;
    }
    int Line::getLength( void )
    {
    return *ptr;
    }
    
    void display(Line obj)
    {
       cout << "Length of line : " << obj.getLength() <<endl;
    }
    
    // Main function for the program
    int main( )
    {
       Line line(10);
    
       display(line);
    
      return 0;
    }
    

    the result is :

    Normal constructor allocating ptr
    Copy constructor allocating ptr.
    Length of line : 10
    Freeing memory!
    Freeing memory!
    

    and when I commented out (the copy constructor) and the code inside destructor I got the same results:

    Normal constructor allocating ptr
    Length of line : 10
    

    So what is the difference between using the copy constructor here or not? Also why does "Freeing Memory!" occur twice?