【问题标题】:C++ Deep and Shallow CopyC++ 深浅复制
【发布时间】:2020-06-21 15:04:45
【问题描述】:

我需要包含浅拷贝构造函数,我完全迷路了。我认为编译器提供了一个默认的浅拷贝构造函数,但我也必须提供一个,但我不确定如何编写它。我尝试编写它类似于 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;
}

【问题讨论】:

  • 你的浅拷贝 pca = wad.pca 中有没有这行?如果是这样,什么不起作用?
  • 旁白:你#include &lt;string&gt;,但不要使用任何std::strings,即使它们在这里非常有用
  • 我不认为我可以像那样分配新的 WrapArrayShallow 对象的数组,但它确实有效,谢谢你stackoverblast!
  • 最后一条语句“更改数组后,WrapArrayShallow 的两个数组都应为空。”为什么你期望它们都是空的?或者你的意思是不是空的?

标签: c++ deep-copy shallow-copy


【解决方案1】:

从表面上看,深拷贝管理每个变量,包括动态分配的变量并安全地复制到目标对象,而浅拷贝不太关心动态变量。你可能读得很好 here

【讨论】:

    【解决方案2】:

    当你复制 WrapArrayShallow 时,现在有两个指针指向同一个数组,而当 WrapArrayShallow 中的任何一个被销毁时,你 delete[] 数组。

    当第二个WrapArrayShallow 被销毁而你delete[] pca 时,您的程序表现出未定义的行为,它使用了一个已失效的指针。

    您需要在不同的WrapArrayShallow 对象之间进行协调,以便最后一个幸存者delete[]s 销毁数组。最简单的方法是使用std::shared_ptr&lt;char[]&gt; 而不是char *

    【讨论】: