0

I need to include shallow copy constructor and I'm completely lost. I thought that the compiler provided a default shallow copy constructor but I have to provide one as well but I'm not sure how to write it. I tried writing it similar to the WrapArrayDeep copy constructor without the pointers but that didn't work. After altering the array both arrays for WrapArrayShallow should be empty.

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#pragma warning(disable: 4996)
using namespace std;

class WrapArrayDeep
{

    public:
        WrapArrayDeep() 
        {
            capacity = 5;
            pca = new char[capacity];
            
            for(int i = 0;i < capacity;i++)
                *(pca+i) = (97+i);
        } //ends default constructor
        
        WrapArrayDeep(const WrapArrayDeep& wad) //deep copy
        {
            capacity = wad.getCapacity();
            pca = new char[capacity];
            
            for (int i = 0;i < capacity;i++)
                *(pca+i) = wad.pca[i];
        } //ends copy constructor
        
        ~WrapArrayDeep()
        {
            cout << "destructor for WrapArrayDeep!\n";
            delete [] pca;
            
        } //ends destructor
        
        void printArr()
        {
            for(int i = 0;i < capacity;i++)
                cout << pca[i] << " ";
            
            cout << endl;
        } //ends print
        
        void alterArr()
        {
            for(int i = 0;i < capacity;i++)
                *(pca + i) = (123+i);
        }
    
        int getCapacity() const
        {
            return capacity;
        }
    
        WrapArrayDeep& operator =(const WrapArrayDeep& wad)
        {
            if(capacity != wad.capacity)
            {
                delete [] pca;
                pca = new char[wad.capacity];
            }
            
            capacity = wad.capacity;
            for(int i =0;i < capacity;i++)
                pca[i] = wad.pca[i];
                
            return *this;
        } //end of = operator overload
        
    private:
        int capacity;
        char *pca;
};

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

class WrapArrayShallow
{
    public:
        WrapArrayShallow()
        {
            capacity = 5;
            pca = new char[capacity];
            for(int i = 0;i < capacity;i++)
                pca[i] = (97+i);
        } //ends default constructor
        
        ~WrapArrayShallow()
        {
            cout << "destructor for WrapArrayShallow!\n";
            delete [] pca;
        } //ends destructor
        
        void printArr()
        {
            for(int i = 0;i < capacity;i++)
                cout << *(pca + i) << " ";
        }
        
        void alterArr()
        {
            for(int i = 0;i < capacity;i++)
                pca[i] = (123 + i);
        }
        
        int getCapacity() const
        {
            return capacity;
        }
        
    private:
        int capacity;
        char *pca;
};

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
 int main()
 {
    //~~~~~~~~Part 1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
      cout << "Part 1\n";
     int i = 7;
     int *pi;
     pi = &i;
     
     cout << "i = " << i << endl << "pi = " << pi << endl << "*pi = " << *pi << endl;
     
     cout << "address of i = " << &i << endl << "address of pi = " << &pi << endl;
     
     int **ppi;
     ppi = &pi;
     
     cout << "ppi = " << ppi << endl << "*ppi = " << *ppi << endl;
     
     cout << "address of ppi = " << &ppi << endl << "**ppi = " <<**ppi <<endl;
     cout << endl << "~~~~~~~~~~~~~~~~~~~~~~~~~~~";

    //~~~~~~~~Part 2~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    cout << "\nPart 2\n";
    cout << "This section instantiates a wrapper class for a dynamic array of 5 elements. \n";
    
    WrapArrayDeep wad1, *wad2;
    cout <<"WrapArray Deep 1\n";
    wad1.printArr();
    
    //deep copy of wad1
    wad2 = new WrapArrayDeep(wad1);
    cout << "WrapArrayDeep 2 ~ copy constructor \n";
    wad2->printArr();
     
    wad1.alterArr();
    cout << "after altering WrapArrayDeep1, 1 and 2 = \n";
    wad1.printArr();
    wad2->printArr();
     
    WrapArrayShallow was1, *was2;
    cout << "WrapArrayShallow1\n";
    was1.printArr();
     
    //shallow copy of was1
    was2 = new WrapArrayShallow(was1);
    cout << "\nWrapArrayShallow2\n";
    was2->printArr();
     
    was1.alterArr();
    cout << "\nafter altering WrapArrayShallow1, 1 and 2 = \n";
    was1.printArr();
    cout << endl;
    was2->printArr();
     
    cout << endl;

    delete wad2;
    delete was2;
    
    cout << endl;
    system("pause");
    return 0;
}
brianh
  • 15
  • 2
  • Did you have this line in your shallow copy pca = wad.pca? If so, what did not work? – stackoverblown Jun 21 '20 at 16:02
  • Aside: you `#include `, but don't use any `std::string`s, even though they would be very useful here – Caleth Jun 21 '20 at 16:11
  • I didn't think I could assign the new WrapArrayShallow object's array like that but it did work thank you stackoverblown! – brianh Jun 21 '20 at 16:18
  • The last statement "After altering the array both arrays for WrapArrayShallow should be empty." Why did you expect them to be both empty? Or did you mean not empty? – stackoverblown Jun 21 '20 at 18:02

2 Answers2

1

To describe at the surface, Deep copy manages every variables including dynamically allocated one and safely copy to the destination object while the shallow copy don't care much about the dynamic variables. You might have a good read here

Sudip Ghimire
  • 677
  • 6
  • 15
0

When you copy a WrapArrayShallow, there are now two pointers pointing to the same array, and when either WrapArrayShallow is destroyed, you delete[] the array.

Your program exhibits undefined behaviour, it uses a pointer that has been invalidated, when the second WrapArrayShallow is destroyed, and you delete[] pca.

You need to co-ordinate between the different WrapArrayShallow objects such that the last survivor delete[]s the array when it is destroyed. The simplest way is to use a std::shared_ptr<char[]> instead of a char *

Caleth
  • 52,200
  • 2
  • 44
  • 75