C ++ Глубокая и поверхностная копия - PullRequest
0 голосов
/ 21 июня 2020

Мне нужно включить конструктор мелких копий, и я полностью потерялся. Я думал, что компилятор предоставил конструктор неглубокого копирования по умолчанию, но я тоже должен предоставить его, но я не уверен, как его написать. Я попытался написать его аналогично конструктору копирования WrapArrayDeep без указателей, но это не сработало. После изменения массива оба массива для WrapArrayShallow должны быть пустыми.

#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;
}

Ответы [ 2 ]

0 голосов
/ 21 июня 2020

Когда вы копируете WrapArrayShallow, теперь есть два указателя, указывающие на один и тот же массив, и когда любой WrapArrayShallow уничтожается, вы delete[] массив.

Ваша программа демонстрирует неопределенное поведение, он использует указатель, который был признан недействительным, когда второй WrapArrayShallow уничтожен, и вы delete[] pca.

Вам необходимо координировать действия между различными WrapArrayShallow объектами, чтобы последний оставшийся в живых delete[] s массив, когда он уничтожен. Самый простой способ - использовать std::shared_ptr<char[]> вместо char *

0 голосов
/ 21 июня 2020

Чтобы описать на поверхности, глубокая копия управляет всеми переменными, включая динамически выделяемую переменную, и безопасное копирование в целевой объект, в то время как мелкая копия не заботится о динамических c переменных. Вы могли бы хорошо прочитать здесь

...